Educational Codeforces Round 136 (Rated for Div. 2) E. Cleaning Robot
题意:有一个二行n列的网格,有一些网格是脏的,扫地机器人起点在(1,1) 保证起点干净。
扫地机器人的的路线如下:每次去离他曼哈顿距离最近的脏的点,并使之干净。现在请问网格能留下最多多少个点,能使机器人一直工作完不冲突。
不冲突指:不存在两个脏的地方都是距离它曼哈顿距离最近的点。
题解:
首先显然机器人只会从左到右运行。
DP ,考虑状态 f(0/1,i)当前走到第0/1层的第i列时,所能收集到最多的1 (即脏地方)。
如果机器人在0行,一直往右走时,如果下方不是1,那么可以不用转移到下方,因为可以在后面某个下方为1的时候转移。
1、对立行不是1,f(j,i) j行i列,s[j^1][i] != 1 f(j,i+1) = f(j,i)+s[j][i+1]
2、对立行是1 , f(j,i) j行i列,s[j^1][i] == 1
那么分为两种情况
1)右边不是1 则可以直接去到下方 f(j^1,i) = f(j,i) + s[j^1][j] (注意这里要用变量存储更新,否则会循环dp,并且最后进行,因为2)是用原来的值 )
2)右边是1 则可以直接向右走,或者从对立行向右走2格子(因为一定不能走到右边的1)。
上面的f(i,j)的更新都是取max,最后取一个ans = max({ans,f[0][i],f[1][i]) ,我一般i喜欢取到n多一些,防止出错。
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N = 2e5 + 10; int f[2][N],s[2][N]; char str[2][N]; int n; void chkmax(int &u,int v){ u = max(u,v); } int main(){ // freopen("a.txt","r",stdin); scanf("%d",&n); scanf("%s%s",str[0]+1,str[1]+1); for(int i = 1;i<=n;++i){ s[0][i] = str[0][i] - '0'; s[1][i] = str[1][i] - '0'; } memset(f,-0x3f,sizeof f); f[0][0] = 0; int ans = 0; for(int i = 0;i<=n+2;++i){ if(s[1][i] == 1 && s[0][i+1] == 1){ chkmax(f[1][i+2],f[0][i]+1+s[1][i+1]+s[1][i+2]); } if(s[0][i] == 1 && s[1][i+1] == 1){ chkmax(f[0][i+2],f[1][i]+1+s[0][i+1]+s[0][i+2]); } int t0 = f[0][i],t1 = f[1][i]; if(s[1][i] == 1 && s[0][i+1] == 0){ chkmax(f[1][i],t0+1); } if(s[0][i] == 1 && s[1][i+1] == 0){ chkmax(f[0][i],t1+1); } // 情况 1) 2) 的公共部分 for(int j = 0;j<2;++j){ chkmax(f[j][i+1],f[j][i]+s[j][i+1]); } chkmax(ans,max(f[0][i],f[1][i])); // cout<<i<<" "<<f[0][i]<<" "<<f[1][i]<<'\n'; } printf("%d\n",ans); return 0; }
标签:Educational,Rated,int,机器人,Codeforces,136,Div From: https://www.cnblogs.com/wanghai673/p/16745905.html