一道动态规划的题目。
总是搞不清递推关系,第一次的错误的递推关系竟然还有个22分。。。
//20' 因为DP的递推写错了。。。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
int num[20];
int dp[20][20];
int main()
{
int n,k;
memset(num,0,sizeof(num));
memset(dp,0,sizeof(dp));
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>num[i];
dp[1][0]=num[1];
for(int i=2;i<=n;i++)
{
for(int j=0;j<=k;j++)
{
if(j>=k)
{
dp[i][j]=dp[i-1][j];
}
dp[i][j] = max(dp[i-1][j]+num[i] , dp[i-1][j-1]*num[i]);
//这是错误的
}
}
cout<<dp[n][k]<<endl;
return 0;
}
举个例子:
3 2
0 7 4
这个错误的程序会输出28.
为什么呢? 因为递推的时候,没有考虑到下一步能不能乘???(是不是这样理解啊)所以,幸运的是,竟然有个22分。
正确的想法应该是,枚举i 个元素,j 个乘号,,k表示乘号的位置。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
long long dp[30][30];// 不能开成 int,否则88'
long long num[30];
int main()
{
int m,n;
cin>>m>>n;
int ans=0;
for(int i=1;i<=m;i++)
{
cin>>num[i];
ans+=num[i];
dp[i][0]=ans;
}
for(int i=1;i<=m;i++)//前i个数
{
for(int j=1;j<=i-1 ;j++)//有j个乘号
{
for(int k=2;k<=i;k++)// 在第k个元素前 加上 *
{
dp[i][j]=max(dp[i][j],dp[k-1][j-1]*(dp[i][0]-dp[k-1][0]));
}
}
}
cout<<dp[m][n];//<<endl;
return 0;
}
如果88分的话,,看一下自己存储结果的数组是不是int ,得用long long 类型。