Optimal Addition Expression (Dynamic Programming)

Question: There is a number containing n 1-9, add m plus signs in the middle, and find the smallest result

Ideas: Dynamic regularization, using recursion, v(n,m).

For example

12345 

Add 2 plus signs to 5 numbers, at this time n=5, m=2

Assuming the last plus sign is after 4, then 1+234+5 or 12+34+5 or 123+4+5

Assuming the last plus sign is after 3, then 1+23+45 or 12+3+45,

Assuming the last plus sign is after 2, then 1+2+345

See the commonalities, when the last plus sign is added to the ith number, the following numbers are left unchanged

For example, add 5 at the end of example 1, add 45 at the end of example 2, and add 345 at the end of example 3

So, what's next?

We just need to recursively find the previous one according to this principle.

For example, example 1 is to find the minimum value of 1234, example 2 is to find the minimum value of 123, and example 3 is to find the minimum value of 12 (a plus sign in the middle)


Here is the code:

#include <cstdio>  
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <stack>
#include <queue>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define NINF 0xc0c0c0c0
ll dp[111][111];
ll num[111];//initial value
ll number[111][111];//Define a number[i][j], representing the integer from the i-th number to the j-th number
void set(int n)//initialize the number array
{
	for(int i = 1;i <= n;i++)
	{
		number[i][i] = num[i];
		for(int j = i+1;j <= n;j++)
			number[i][j] = number[i][j-1]*10+num[j];
	}
}
ll V(int n,int m)
{
	if(m == 0)//When m is equal to 0, it means that the plus sign is not inserted, then the result is equal to the integer composed of the 1st to the nth number
		return number[1][n];
	else if(n <= m)//n numbers insert at most n-1 plus signs? initialized to the maximum value so that it has no effect
		return INF;
	else
	{
		if(dp[n][m] != 0)
			return dp[n][m];//Prevent timeout
		long long fin = INF;
		for(int i = m;i <= n-1;i++)//loop from the mth number to the penultimate number to find the minimum value
			fin = min(fin,V(i,m-1)+number[i+1][n]);
		return dp[n][m] = fin;
	}
}
intmain()
{
	int n,m;
	while(cin >> n >>m)
	{
		for(int i = 1;i <= n;i++)
			cin >> num[i];
		set(n);
		memset(dp,0,sizeof(dp));
		cout << V(n,m) <<endl;
	}
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325581795&siteId=291194637