寻找线性增长的量的dp

题意:给你一行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;
}
原文地址:https://www.cnblogs.com/rainyskywx/p/11230081.html