暴力显然不行,所以考虑dp
记f[i][j][k][l]为使用i张1,j张2,k张3,l张4所得到的最大分数。
对于每个f[i][j][k][l],都可以由i-1张1,j张2,k张3,l张4所得到,
或者i张1,j-1张2,k张3,l张4所得到,
或者i张1,j张2,k-1张3,l张4所得到,
i张1,j张2,k张3,l-1张4所得到 的最大分数,
四者取max。
当然,还需加上它当前位置的分数。
当前位置为a[i+j*2+k*3+l*4+1](初始位置是1)
代码如下:
#include<iostream> #include<cstring> using namespace std; int f[41][41][41][41]; int s[360]; int n,m; int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ cin>>s[i]; } int a,b,c,d; a=b=c=d=0; int x; for(int i=1;i<=m;i++){ cin>>x; switch(x){ case 1:a++;break; case 2:b++;break; case 3:c++;break; case 4:d++;break; } } for(int i=0;i<=a;i++){ for(int j=0;j<=b;j++){ for(int k=0;k<=c;k++){ for(int l=0;l<=d;l++){ int& ans=f[i][j][k][l]; if(i>0)ans=max(ans,f[i-1][j][k][l]); if(j>0)ans=max(ans,f[i][j-1][k][l]); if(k>0)ans=max(ans,f[i][j][k-1][l]); if(l>0)ans=max(ans,f[i][j][k][l-1]); ans+=s[i+j*2+k*3+l*4+1]; } } } } cout<<f[a][b][c][d]; return 0; }
在编写这个程序的过程中犯了一点小错误,在循环开始前把f[0][0][0][0]=s[1]
自认为考虑非常周到,把边界写上了,其实不用
在循环i=j=k=l=0的时候4个if都不进,最后ans+=s[i+j*2+k*3+l*4+1]其实已经把s[1]的值赋值给f[0][0][0][0]了,前面再画蛇添足就是错误的。
看来边界问题是一个非常有趣(坑)的问题啊...