CF41D Pawn(三维DP)

翻译: 题目描述: 国际象棋棋盘最底行站了一个兵。 它只有两种行动方式: 向上左或向上右走。 它可以选择从最低行哪个节点开始他的旅程。 每个格子上有0-9颗豌豆,而士兵想移动到最上一行并且积累到尽可能多的豌豆。同时,因为这个士兵必须把豌豆平均分给自己和他的k个兄弟,他所收集到的豌豆必须是k+1的倍数。请找到他可以收集到的最多豌豆,并确定他的操作序列。

规定士兵不能手动扔出豌豆,并且他必须捡起所到达的每一个格子的所有豌豆。

输入格式: 第一行三个整数n,m,k(2 <= n,m <= 100, 0 <= k <= 10)2<=n,m<=100,0<=k<=10) 行数、列数、士兵的兄弟们。 接下来一个n \times mn×m的矩阵,每个元素均是0-9的整数(不空格),描述该格的豌豆。第一行被认为是最上一行,最后一行被认为是最下一行。

输出格式:

如果不能收集到k+1倍数的豌豆,输出-1. 否则,输出第一行一个整数,为最多豌豆数;第二行一个整数,为士兵开始移动的位置;第三行包括n-1个字母L 或 R,表示士兵的行动序列。

如果有多种收集到相同且是k+1倍数数量的豌豆,你可以任意输出一种方案。 Translated by @Maniac丶坚果

题解:

#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int a[maxn][maxn];
string s[maxn];
int n,m,p;
int dp[maxn][maxn][15];
int visit[maxn][maxn][15];
//dp(i,j,k)表示第i行第j列的答案在模p的值等于k的前提下的最大值
int main () {
    scanf("%d%d%d",&n,&m,&p);
    p++;
    for (int i=0;i<n;i++) cin>>s[i];
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            a[i][j]=s[i-1][j-1]-'0';
    for (int i=1;i<=m;i++) visit[n][i][a[n][i]%p]=1,dp[n][i][a[n][i]%p]=a[n][i];
    for (int i=n-1;i>=1;i--) {
        for (int j=1;j<=m;j++) {
            for (int k=0;k<p;k++) {
                if (visit[i+1][j-1][k]) {
                    visit[i][j][(dp[i+1][j-1][k]+a[i][j])%p]=1;
                    dp[i][j][(dp[i+1][j-1][k]+a[i][j])%p]=max(dp[i][j][(dp[i+1][j-1][k]+a[i][j])%p],dp[i+1][j-1][k]+a[i][j]);
                }
                if (visit[i+1][j+1][k]) {
                    visit[i][j][(dp[i+1][j+1][k]+a[i][j])%p]=1;
                    dp[i][j][(dp[i+1][j+1][k]+a[i][j])%p]=max(dp[i][j][(dp[i+1][j+1][k]+a[i][j])%p],dp[i+1][j+1][k]+a[i][j]);
                }
            } 
        }
    }
    int ans=-1;
    int u=-1;
    for (int i=1;i<=m;i++) {
        if (visit[1][i][0]&&dp[1][i][0]>ans) {
            ans=dp[1][i][0];
            u=i;
        }
    }
    printf("%d\n",ans);
    if (ans==-1) return 0;
    string wjm="";
    int k=0;
    for (int i=1;i<n;i++) {
        int tt=dp[i][u][k]-a[i][u];
        k=tt%p;
        if (visit[i+1][u-1][k]&&dp[i+1][u-1][k]==tt) {
            wjm.push_back('R');
            u--;
        }
        else {
            wjm.push_back('L');
            u++;
        }
    }
    reverse(wjm.begin(),wjm.end());
    printf("%d\n",u);
    cout<<wjm<<"\n";
} 

 

posted @ 2020-08-12 15:49  zlc0405  阅读(128)  评论(0编辑  收藏  举报