3 4 5 6 10 9 11 0
199
Wa了好几次才发现自己真是图样图森破→_→ 开始还自作聪明的把当前人数这个数组改成数字了 怎么不想想真要是照着我这么写 连DP数组也不用写了 ╭(╯^╰)╮
而且 当时只是顾得递推关系中后面的最优解一定是由前面的最优解得来的 而没有注意到这个最优解应该是由几个状态转化而来的 而不是一个状态经过不同操作转化而来的
却说现在还没想到针对于自己之前错误思路的反例 但是理解了正确代码中除了月份循环以外的二重的意义:类似于上一个DP 1024max sumsum plusplus 中滚动数组状态对应取最优的思想
先贴错误代码:
#include <iostream> #include<cstdio> #include<cstring> using namespace std; long long hire,salary,fire; int n; long long minn[1000],tmp,dp[10000];///tmp不用设成数组 有数字就行(⊙﹏⊙)b int main() { while(~scanf("%d",&n)&&n) { scanf("%lld%lld%lld",&hire,&salary,&fire); memset(dp,0,sizeof(dp)); memset(minn,0,sizeof(minn)); for(int i=0;i<n;i++) scanf("%lld",&minn[i]); dp[0]=(salary+hire)*minn[0]; tmp=minn[0]; for(int i=1;i<n;i++) { if(tmp<minn[i]) { dp[i]=dp[i-1]+(hire)*(minn[i]-tmp)+salary*minn[i]; tmp=minn[i]; } else if(tmp==minn[i]) dp[i]=dp[i-1]+tmp*salary; else { int tmp1=dp[i-1]+fire*(tmp-minn[i])+salary*minn[i]; int tmp2=dp[i-1]+salary*tmp; if(tmp1<=tmp2) { dp[i]=tmp1; tmp=minn[i]; } else{ dp[i]=tmp2; } } } printf("%lld\n",dp[n-1]); } return 0; }
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int hire,salary,fire; int n; int minn[1000],tmp,dp[20][1000],maxn,mmin;///tmp不用设成数组 有数字就行(⊙﹏⊙)b int main() { while(~scanf("%d",&n)&&n) { scanf("%d%d%d",&hire,&salary,&fire); // memset(dp,0,sizeof(dp)); //memset(minn,0,sizeof(minn)); maxn=0; for(int i=1;i<=n;i++) { scanf("%d",&minn[i]); maxn=max(maxn,minn[i]); } for(int i=minn[1];i<=maxn;i++) dp[1][i]=(salary+hire)*i; for(int i=2;i<=n;i++) { for(int j=minn[i];j<=maxn;j++)//now { mmin=0x3f3f3f3f; for(int k=minn[i-1];k<=maxn;k++)//last { if(j>k) tmp=dp[i-1][k]+hire*(j-k)+salary*j; else tmp=dp[i-1][k]+fire*(k-j)+salary*j; if(tmp<mmin) mmin=tmp; } dp[i][j]=mmin; } } mmin=0x3f3f3f3f;/// for(int i=minn[n];i<=maxn;i++) { if(dp[n][i]<mmin) mmin=dp[n][i]; } printf("%d\n",mmin); } return 0; }