zzd 的割草机(Lawnmower)
【题目描述】
已知花坛为一个 n * m 的矩形,草只会长在某些个格子上,zzd 有一个割草机,一开始,
zzd 站在(1,1)处,面向(1,m)(面向右).每次 zzd 有两个选择(耗费一个单位时间):
1:向自己面朝的方向移动一格。
2:向下移动一格,并改变自己的朝向。
但 zzd 不能向上移动,也不能后退,因为他喜欢 DP,不想有后效性.
只要 zzd 移动到有杂草的格子,zzd 会清除杂草(不需要耗时)。现在,zzd 想知道最少要耗费多少时间才能清除所有杂草。
【输入】
第一行 n,m. 接下来 n 行,每行 m 个字符,其中'W'表示杂草,'G'表示空地。
【输出】
至少要耗费多少时间才能清除所有杂草。
【样例】
Lawnmower.in
4 5
GWGGW
GGWGG
GWGGG
WGGGG
Lawnmower.out
11【数据范围】
n,m<=150
思路:
虽然zzd很喜欢DP 但是我并不知道怎么用DP做 ???
感觉是模拟啊
由题目可以知道:在奇数行 zzd的方向一定是向右的
在偶数行 zzd的方向一定是向左的
然后算出每行走到什么位置就可以了
输入的时候只要存 l[ ],r[ ] 表示每行最左边的杂草的列数 和最右边的杂草列数
再记一下每一行的总杂草数s[ ] 就可以啦
然后特别要注意特判 考虑几种特殊情况:
1.这一行没有杂草 但是下一行有
假如这一行要向左走 那么取 min的时候就会选到0了
2.这一行没有杂草 并且此时要向左走 但是下一行有
但是下一行最左边的杂草在现在所在位置的右边
如果不特判它对答案的贡献将为负
3.还有几行格子没走完 但是已经清理完所有的杂草了
直接输出答案结束程序即可
还有一个注意的点,关于统计答案的:
假如这行从 a 走到 b 那么ans+=b-a+1
后面这个+1是因为 走完这一行之后就要向下走到下一行
但是当你割最后一束杂草的时候是不需要再往下走了
所以最后的 ans 要 -1
CODE:
View Code1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #define go(i,a,b) for(register int i=a;i<=b;i++) 5 #define yes(i,a,b) for(register int i=a;i>=b;i--) 6 #define M 150+10 7 using namespace std; 8 int read() 9 { 10 int x=0,y=1;char c=getchar(); 11 while(c<'0'||c>'9') {if(c=='-') y=-1;c=getchar();} 12 while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();} 13 return x*y; 14 } 15 string s; 16 int n,m,ans,nw=1,res,l[M],r[M],sm[M]; 17 int main() 18 { 19 freopen("Lawnmower.in","r",stdin); 20 freopen("Lawnmower.out","w",stdout); 21 n=read();m=read(); 22 go(i,1,n) 23 { 24 cin>>s; 25 go(j,0,m-1) if(s[j]=='W') { if(!l[i]) l[i]=j+1; r[i]=j+1;sm[i]++;res++;} 26 } 27 go(i,1,n) 28 { 29 if(i%2) //奇数行 30 { 31 int right=max(r[i],r[i+1]); 32 if(!right && i==n) right=r[i]; 33 if(!right || right<nw) right=nw; 34 ans+=right-nw+1;nw=right;res-=sm[i]; 35 } 36 else //偶数行 37 { 38 int left=min(l[i],l[i+1]); 39 if(!left && l[i]) left=l[i]; 40 if(!left && l[i+1]) left=l[i+1]; 41 if(!left || left>nw) left=nw; 42 ans+=nw-left+1;nw=left;res-=sm[i]; 43 } 44 if(!res) break ; 45 } 46 printf("%d",ans-1); 47 return 0; 48 }