2 条题解

  • 1
    @ 2025-03-23 16:47:58

    #include<cstdio>
    #define max(a,b) a>b?a:b
    #define r(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    int f[41][41][41],a[351],n,m,g[4],t;
    int main()
    {
    scanf("%d%d",&n,&m);
    r(i,1,n) scanf("%d",&a[i]);
    while(m--) {scanf("%d",&t);g[t-1]++;}
    f[0][0][0]=0;
    r(i,0,g[0])
    r(j,0,g[1])
    r(k,0,g[2])
    r(l,0,g[3])
    {
    t=a[1+i+(j<<1)+k*3+(l<<2)];
    if(j) f[j][k][l]=max(f[j][k][l],f[j-1][k][l]);
    if(k) f[j][k][l]=max(f[j][k][l],f[j][k-1][l]);
    if(l) f[j][k][l]=max(f[j][k][l],f[j][k][l-1]);
    f[j][k][l]+=t;
    }
    printf("%d",f[g[1]][g[2]][g[3]]);
    }

  • -1
    @ 2025-03-23 16:48:20

    由于题目告诉我们确保用完牌恰好能走完,题目被大大简化
    我们用数组dp[a][b][c][d]表示用了a张一步牌,b张2步牌,c张3步牌,d张4布牌所能得到的最高分
    num[i-1]表示i步牌的张数;path[]数组记录路径信息;card[]数组记录卡牌信息。
    则有dp[0][0][0][0]=path[0]//什么牌都不用就可以获得起点的分数
    并且有**path[a+2b+3c+4d]为当前点的分数**
    之后四重循环,分别枚举a,b,c,d;
    对于枚举的每种情况:
    dp[a][b][c][d]=max(dp[a][b][c][d],**之前的一步操作**+**[a+2b+3c+4d]**)
    这句话的意思是:**是不进行前一步操作比较赚还是进行比较赚**
    为什么要判断a,b,c,d是否大于0呢?**都没牌了哪里还存在前一步操作呢?**
    ok!最后答案被保存在dp[num[0]][[num[1]][num[2]][num[3]]里,输出即可。
    talk is cheap shou me the code:
    #include<iostream>
    using namespace std;
    int N,M,pv,num[4],path[500],card[500],dp[42][42][42][42];
    int main()
    {
    cin>>N>>M;
    for(int i=0;i<N;i++)cin>>path[i];
    for(int i=0;i<M;i++){cin>>card[i];num[card[i]-1]+=1;}
    dp[0][0][0][0]=path[0];
    for(int a=0;a<=num[0];a++)
    for(int b=0;b<=num[1];b++)
    for(int c=0;c<=num[2];c++)
    for(int d=0;d<=num[3];d++)
    {pv=a+b*2+c*3+d*4;
    if(a>0) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a-1][b][c][d]+path[pv]);
    if(b>0) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b-1][c][d]+path[pv]);
    if(c>0) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b][c-1][d]+path[pv]);
    if(d>0) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b][c][d-1]+path[pv]);}
    cout<<dp[num[0]][num[1]][num[2]][num[3]];
    return 0;
    }

  • 1

信息

ID
1351
难度
6
分类
动态规划 点击显示
标签
递交数
16
已通过
11
通过率
69%
上传者