CF1739 EDU E
题意:给定一个
(距离的定义是横坐标之差的绝对值加上纵坐标之差的绝对值)
由于是
那么考虑DP,其实这时已经有大量设计状态的方式了。
为了状态的方便,我们试着转换一下题意,改为找一条路径使得路径上没有一个脏格子与另外两个脏格子距离最短且一样,并使得这条路径上的脏格子最多。那么路径之外的脏格子可以全部抹除。
在这里我设
那么每走到一个格子,我们有两种方案:
1.无视同一列的另一个格子,直接向右走。(这里
2.换一行。换一行的必要条件是另一行是脏格子且下一列的同行不是脏格子(或者将那里的脏格子抹除)。值得注意的是可能出现能换行但另一行不是脏格子的情况,如
x0
01
(机器人在
但此时你可以先向右移动再向下,两种情况等价。
为了方便解释,我给出一个例子。
1 2 3
a x 1 1
b 1 1 1
如果要换行,那么我们要求
所以如果换行,那么有
同理,如果需要在下一列就换行也是和下下列再换行等价的。所以该状态转移方程成立。
#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
int a[maxn][2];
int f[maxn][2];//第i列 从上/下进入
char s[2][maxn];
inline int Max(int a,int b){
return a>b?a:b;
}
int main(){
int n;scanf("%d",&n);
for(int i=0;i<2;i++)
scanf("%s",s[i]+1);
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++) a[j][i]=s[i][j]-'0';
/*for(int i=0;i<2;i++){
for(int j=1;j<=n;j++) {
cout<<a[j][i];
}
puts("");
}*/
for(int i=0;i<2;i++) for(int j=1;j<=n;j++) f[j][i]=-(1<<30);
f[1][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=1;j++){
f[i+1][j]=Max(f[i+1][j],f[i][j]+a[i+1][j]); //直接向右走 另外一格有则清
if(a[i][!j]) //如果想要换一行,那么下一行必须得是脏的,且下一列的同行得清掉
f[i+2][!j]=Max(f[i+2][!j],f[i][j]+a[i][!j]+a[i+1][!j]+a[i+2][!j]);
}
}
return printf("%d\n",Max(Max(f[n+1][0],f[n+1][1]),Max(f[n+2][0],f[n+2][1]))),0;
}