D. Pawn(記憶化搜索)

https://codeforces.com/contest/41/problem/D

題意翻譯

翻譯: 題目描述: 國際象棋棋盤最底行站了一個兵。 它只有兩種行動方式: 向上左或向上右走。 它可以選擇從最低行哪個節點開始他的旅程。 每個格子上有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倍數數量的豌豆,你可以任意輸出一種方案。 

 

 

這題和數塔很相似,不過是多了一個要求就是還要滿足獲得的最大值是K+1的倍數,那麼只需要多定義一維表示模K+1爲多少的狀態即可,定義dp[i][j][k]爲從i,j爲起點往下走能獲得的最大值,且最大值模K+1爲k。 轉移的話就由它的左下角格子和右下角格子轉移來即可,用的是填表法,不過大佬說可以用刷表法寫,感覺應該差不多。

#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)+1
#define ll long long
#define fuck(x) cout<<#x<<"     "<<x<<endl;
typedef pair<int,int>pii;
const int maxn=1e6+10;
int d[4][2]= {1,0,-1,0,0,1,0,-1};
int dp[105][105][15],mp[105][105],vis[105][105],n,m,k;
pii path[105][105][15];
void dfs(int x,int y)
{
    if(vis[x][y]||x>n||x<1||y>m||y<1)
        return ;
    vis[x][y]=1;
    dfs(x+1,y-1);
    dfs(x+1,y+1);
    for(int i=0; i<=k; i++)
    {
        if(dp[x+1][y+1][i]!=-1&&dp[x][y][(i+mp[x][y])%(k+1)]<dp[x+1][y+1][i]+mp[x][y])
            dp[x][y][(i + mp[x][y]) % (k + 1)] = dp[x + 1][y + 1][i] + mp[x][y], path[x][y][(i + mp[x][y]) %(k + 1)] = make_pair(x + 1, y + 1);
        if(dp[x+1][y-1][i]!=-1&&dp[x][y][(i+mp[x][y])%(k+1)]<dp[x+1][y-1][i]+mp[x][y])
            dp[x][y][(i + mp[x][y]) % (k + 1)] = dp[x + 1][y - 1][i] + mp[x][y], path[x][y][(i + mp[x][y]) %(k + 1)] = make_pair(x + 1, y - 1);
    }
}
int main(){
    stack<pii>sta;
    int maxx=-1,pos,mod=0,tmp;
    memset(dp,-1,sizeof(dp));
    while(!sta.empty())
        sta.pop();
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
        {
            char ch;
            scanf(" %c",&ch);
            mp[i][j]=ch-'0';
        }
    for(int j=1;j<=m;j++){
        vis[n][j]=1;
        dp[n][j][mp[n][j]%(k+1)]=mp[n][j];
    }
    for(int j=1; j<=m; j++)
        dfs(1,j);
    for(int j=1; j<=m; j++)
        if(dp[1][j][0]>maxx)
            maxx=dp[1][j][0],pos=j;
    cout<<maxx<<endl;
    if(maxx!=-1)
    {
        pii now=make_pair(1,pos);
        while(now.first!=0){
            sta.push(make_pair(now.first,now.second));
            tmp=(mod-mp[now.first][now.second]%(k+1)+k+1)%(k+1);
            now=path[now.first][now.second][mod];
            mod=tmp;
        }
        int yy=sta.top().second;sta.pop();
        cout<<yy<<endl;
        while(!sta.empty()){
            if(sta.top().second>yy)
                cout<<"R";
            else
                cout<<"L";
            yy=sta.top().second;
            sta.pop();
        }
        cout<<endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章