CF41D
观察到 \(n,m,k\) 均不大,考虑 dp。
令 \(dp_{i,j,l}\) 表示走到 \((i,j)\) 得到 \(l\) 个豆子可不可能。由于 \(a_{i,j}\le 9\),并且每次移动都会向上移动一行,所以 \(l\le 9\times n\)。
转移较为简单,无非从 \((i+1,j-1)\) 和 \((i+1,j+1)\) 转移,类似数字三角形。
关于答案,就是在 \(1\le j\le m\) 的情况下找到满足下面条件的最大 \(l\)。
-
\(dp_{1,j,l}=1\)
-
\(l\) 在 \(\mod (k+1)\) 意义下为 \(0\)。
暴力枚举即可。
现在考虑如何求出一组路径。
假设答案是在 \(dp_{1,j,l}\) 上找到的,那么 \(dp_{2,j-1,l-a_{1,j}}\) 和 \(dp_{2,j+1,l-a_{1,j}}\) 一定有一个是合法的(不然怎么转移过来)。于是我们可以倒退路径,记录每次向哪走即可。
#include<bits/stdc++.h>
#define int long long
template<typename T>
void read(T &x){
int f=1;
char c=getchar();
x=0;
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar();
x*=f;
}
template<typename T,typename I>
void chkmin(T &a,I b){
a=std::min(a,b);
}
template<typename T,typename I>
void chkmax(T &a,T b){
a=std::max(a,b);
}
const int inf=1e18+10,MOD1=998244353,MOD2=1e9+7;
const int maxn=110;
int a[maxn][maxn],dp[maxn][maxn][1100],move[maxn],tot=0;
signed main(){
int n,m,k;
std::cin>>n>>m>>k;
k++;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
char c;
std::cin>>c;
a[i][j]=(int)(c-'0');
}
memset(dp,0,sizeof(dp));
for(int j=1;j<=m;j++) dp[n][j][a[n][j]]=1;
for(int i=n-1;i>=1;i--){
for(int j=1;j<=m;j++){
//dp[i+1][j-1] dp[i+1][j+1]
for(int l=0;l<=900;l++){
if(dp[i+1][j-1][l]) dp[i][j][(l+a[i][j])]=1;
if(dp[i+1][j+1][l]) dp[i][j][(l+a[i][j])]=1;
}
}
}
int ans=-1,ansj=-1,cnt=0;
for(int j=1;j<=m;j++)
for(int l=0;l<=1000;l++){
if(l%k!=0) continue;
if(dp[1][j][l]){
if(l>ans) ans=l,ansj=j;
}
}
printf("%lld\n",ans);
if(ans==-1) return 0;
for(int i=1;i<n;i++){
//去推下一行
ans-=a[i][ansj];
if(ansj-1>0&&dp[i+1][ansj-1][ans]) ansj--,move[++tot]=2;
else ansj++,move[++tot]=1;
}
printf("%lld\n",ansj);
for(int i=tot;i>=1;i--) printf("%c",(move[i]==1?'L':'R'));
return 0;
}
/*
-读入字符一定检查回车
- 能不能搜索?
-函数要有返回值!
-想好了再写!
*/

浙公网安备 33010602011771号