次元传送门:洛谷P4158
思路
f[i][j][k][0/1]表示在坐标为(i,j)的格子 已经涂了k次 (0是此格子涂错 1是此格子涂对)涂对的格子数
显然的是 每次换行都要增加一次次数
那么当j=1时:
f[i][j][k][1]=max(f[i-1][m][k-1][1],f[i-1][m][k-1][0])+1;//可以从前一排最后一个转移过来 记得+1 f[i][j][k][0]=max(f[i-1][m][k-1][1],f[i-1][m][k-1][0]);//同理 不用+1
当j>1时分成两种情况
- 当第i格和第i-1格相同
f[i][j][k][1]=f[i][j-1][k][1]+1;//最优为前一个不换方案即可+1 因为同色 f[i][j][k][0]=max(f[i][j-1][k][0],f[i][j-1][k-1][1]);//如果不对的话 就要从前面也错不换刷子或者前面对换刷子中取最大值
- 当第i格和第i-1格不同
f[i][j][k][1]=max(f[i][j-1][k-1][1]+1,f[i][j-1][k][0]+1);//当前是对的可以从前面是对的但是换刷子或者前面是错的不换刷子中来 记得+1 f[i][j][k][0]=max(f[i][j-1][k][1],f[i][j-1][k-1][0]);//当前是错的可以从前面是对的不用换刷子或者前面是错的但是换刷子中来 不用+1
每次查找都要取ans
因为有可能在任意一格停下
代码
#include<iostream> using namespace std; #define maxn 55 int n,m,t,ans; int map[maxn][maxn]; int f[maxn][maxn][maxn*maxn][2]; int main() { cin>>n>>m>>t; for(int i=1;i<=n;i++)//输入操作 { string s; cin>>s; for(int j=0;j<s.size();j++) map[i][j+1]=s[j]-'0'; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=1;k<=t;k++) { if(j==1)//第一排 { f[i][j][k][1]=max(f[i-1][m][k-1][1],f[i-1][m][k-1][0])+1; f[i][j][k][0]=max(f[i-1][m][k-1][1],f[i-1][m][k-1][0]); } else { if(map[i][j]==map[i][j-1])//相同 { f[i][j][k][1]=f[i][j-1][k][1]+1; f[i][j][k][0]=max(f[i][j-1][k][0],f[i][j-1][k-1][1]); } else//不同 { f[i][j][k][1]=max(f[i][j-1][k-1][1]+1,f[i][j-1][k][0]+1); f[i][j][k][0]=max(f[i][j-1][k][1],f[i][j-1][k-1][0]); } } ans=max(ans,max(f[i][j][k][1],f[i][j][k][0])); } cout<<ans; }
本文详细介绍了洛谷P4158次元传送门问题的动态规划解法,通过四维状态转移方程f[i][j][k][0/1],针对不同颜色格子的涂色过程进行分析,给出具体实现代码。
&spm=1001.2101.3001.5002&articleId=101884881&d=1&t=3&u=ac2b65172a404c3b93e6617823c6bae3)
194

被折叠的 条评论
为什么被折叠?



