题解 CF41D Pawn

基础 DP 题。

定义 fi,j,k 表示从第一行走到 (i,j),且数字总和模 p 等于 k

转移方程为:

fi+1,j1,(k+ai+1,j1)modp=max(fi,j,k+ai+1,j1)

fi+1,j+1,(k+ai+1,j+1)modp=max(fi,j,k+ai+1,j+1)

同时还需要定义 gi,j,k 表示当前状态是由哪一种转移过来的。

注意边界情况。

复杂度 O(n2)

code:

#include<bits/stdc++.h>
using namespace std;
const int N=100+5,inf=INT_MAX/2;
int n,m,p,f[N][N][11],a[N][N],g[N][N][11];
int main(){
  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  cin>>n>>m>>p;++p;
  for(int i=1;i<=n;++i){
    for(int j=1;j<=m;++j){
      char x;cin>>x;
      a[i][j]=x-'0';
      for(int k=0;k<p;++k)f[i][j][k]=-inf;
    }
  }
  for(int j=1;j<=m;++j)f[1][j][a[1][j]%p]=a[1][j];
  for(int i=1;i<n;++i){
    for(int j=1;j<=m;++j){
      for(int k=0;k<p;++k){
        int tk=(k+a[i+1][j-1])%p,val=f[i][j][k];
        if(j>1&&f[i+1][j-1][tk]<val+a[i+1][j-1]){
          f[i+1][j-1][tk]=val+a[i+1][j-1];
          g[i+1][j-1][tk]=1;
        }
        tk=(k+a[i+1][j+1])%p;
        if(j<m&&f[i+1][j+1][tk]<val+a[i+1][j+1]){
          f[i+1][j+1][tk]=val+a[i+1][j+1];
          g[i+1][j+1][tk]=0;
        }
      }
    }
  }
  int w=1;
  for(int j=1;j<=m;++j){
    if(f[n][j][0]>f[n][w][0]){
      w=j;
    }
  }
  if(f[n][w][0]<0){
    cout<<-1<<endl;
    return 0;
  }
  cout<<f[n][w][0]<<endl;
  cout<<w<<endl;
  int i=n,j=w,k=0;
  while(i>=2){
    if(g[i][j][k]){
      cout<<"R";
      k=(k-a[i][j]%p+p)%p;--i;++j;
    }else {
      cout<<"L";
      k=(k-a[i][j]%p+p)%p;--i;--j;
    }
  }
  return 0;
}

本文作者:HQJ2007

本文链接:https://www.cnblogs.com/HQJ2007/p/17561328.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   HQJ2007  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起