NOJ_1017積最大(DP大法)

1445 ワード

抄のビルutadaのコード、リンク:http://blog.csdn.net/Area_52/articale/detail/43540097
そしてTc_を参考にしましたトムTopの記事、リンク:http://blog.csdn.net/Tc_トムTop/articale/detail/40951263
よく記録してください。前にDPの問題をやったことがないからです。
以上の2人のブログを見ないと、この方法は本当に思いつかないです。ここでしばらくしたら諸葛亮です。
数字列を1234、K=2に設定します。
dp[1][0]=1 dp[2][0]=12 dp[3][0]=123 dp[4][0]=1234; 直接入手可能(dp[i][0]の初期化)
その後
dp[2][1]=dp[1][0]**ans(2,2)  dp[3][1]=max(dp[1][0]**ans(2,3)、dp[2][0]*ans(3,3)
dp[4][1]=max(3項...)
次のステップは、前のステップの結果から導き出すことができます。
このようなタイプの問題は、各ステップの結果を記録して、次のステップの結果を導き出すことができると推測されています。最終的に大きな問題を解決します。
コード
#include<stdio.h>
#include<string.h>
#define MAXN 50
int s[MAXN];
char tmp[MAXN];
__int64 dp[MAXN][MAXN];

__int64 ans(int start,int end)
{
	__int64 temp = 0;
	int i;
	for(i=start;i<=end;i++)
	{
		temp *= 10;
		temp += s[i];
	}
	return temp;
}

__int64 max(int i,int j)
{
	int p;
	__int64 tmp = -1;
	for(p=1;p<i;p++)
	{
		if(tmp < dp[p][j-1]*ans(p,i-1))
			tmp = dp[p][j-1]*ans(p,i-1);
	}
	return tmp;
}

int main()
{
	int i,k,j;
	int n;
	scanf("%d %d",&n,&k);
	scanf("%s",tmp);
	for(i=0;i<n;i++)
	{
		s[i] = tmp[i] - '0';
	}
	//dp   
	for(i=1;i<=n;i++)
		dp[i][0] = ans(0,i-1);
	for(j=1;j<=k;j++)
		for(i = j+1;i<=n;i++)
		{
			dp[i][j] = max(i,j);
//			printf("%d %d %I64d
",i,j,dp[i][j]); } printf("%I64d
",dp[n][k]); return 0; }