1. 程式人生 > >NYOJ 整數劃分(四) (區間dp)

NYOJ 整數劃分(四) (區間dp)

題意:給出兩個整數 n , m ,要求在 n 中加入m - 1 個乘號,將n分成m段,求出這m段的最大乘積

思路:區間dp,我們需要先預處理出第i位到第j位可以湊成的數sum[i][j],之後dp[i][j]表示你在第i個數字添加了j個乘號時的最大值,那麼dp[i][j] =max(dp[i][j],dp[k][j-1] * sum[k+1][i])

解釋一下這個dp陣列就是你在第i個數字放第j個乘號的時候,他能從那個狀態轉移過來呢,它可以由第k個數字(k<i)轉移過來,那麼轉移的價值時多大呢,sum[k+1][i],所以dp[i][j] = max(dp[i][j],dp[k][j-i]*sum[k+1][i])

上程式碼把:

#include <bits/stdc++.h>
using namespace std;
string ch;
long long sum[50][50];
long long dp[50][50];
int main()
{
	int t,m;
	cin>>t;
	while(t--)
	{
		ch.clear();
		memset(sum,0,sizeof(sum));
		memset(dp,0,sizeof(dp));
		cin>>ch>>m;
		int len = ch.size();
		for(int i = 0 ; i < len ; i++)
		{
			sum[i][i] = ch[i] - '0';
			for(int j = i+1 ; j < len ; j++)
			{
				sum[i][j] = sum[i][j-1] * 10 + ch[j] -'0';
			}
		}
		for(int i = 0 ; i < len ; i ++)
		{
			dp[i][0] = sum[0][i];
		}
		for(int i = 0 ; i < len ; i++)
		{
			for(int j = 0 ; j < m ;j ++)
			{
				for(int k = 0 ; k < i ;k++)
				{
					dp[i][j] = max(dp[i][j] , dp[k][j-1] * sum[k+1][i]);
				}
			}
		}
		long long ans = -1;
		printf("%lld\n",dp[len-1][m-1]);
	}
}