题意:给你一行a[i]的值,并且你手中有一组纸牌,纸牌上的数字说明你使用这张纸牌时能够向前走多少步。现在小明从a[ 1 ]出发,并且你每到达一个点都会把这个点上的数字加上。现在问当小明把手上的牌用完后,能得到的最大权值和。
思路:一开始我想着以这一行数字的下标作为阶段,然后再用每个人手中的卡牌数量作为
附加的维度来表示当前的状态。但是发现并不可做,因为小明所处的下标并不是线性增长的,
它当前可能走1步也可能走5步,完全取决他出什么纸牌。所以以下标作为阶段不靠谱。所以
只剩下卡牌数可以用来发挥了,因为小明每次只能出一张纸牌,所以,打出去的纸牌的数量是呈线性递增
的,所以打出去的纸牌的数量完全可以当做阶段。现在小明所处的位置就是 1+a+b*2+c*3+d*4,这里一定要加
1,因为小明的起始位置是1。然后为什么dp[ a ][ b ][ c ][ d ]=dp[ a-1 ][ b ][ c ][ d ]每次只能由一个维度减小1推出,因为每次
只出一张牌呗。
#include<bits/stdc++.h> using namespace std; int dp[125][125][125][125]; int n,m; int w[360],card[150]; int a_num,b_num,c_num,d_num; int main() { cin>>n>>m; for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<=m;i++) { cin>>card[i]; if(card[i]==1) a_num++; if(card[i]==2) b_num++; if(card[i]==3) c_num++; if(card[i]==4) d_num++; } dp[0][0][0][0]=w[1]; for(int a=0;a<=a_num;a++) for(int b=0;b<=b_num;b++) for(int c=0;c<=c_num;c++) for(int d=0;d<=d_num;d++) { int r=1+a+b*2+c*3+d*4; if(a>=1) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a-1][b][c][d]+w[r]); if(b>=1) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b-1][c][d]+w[r]); if(c>=1) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b][c-1][d]+w[r]); if(d>=1) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b][c][d-1]+w[r]); } cout<<dp[a_num][b_num][c_num][d_num]; return 0; }