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:

 1 #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 }
View Code
posted @ 2019-01-28 14:48  DTTTTTTT  阅读(268)  评论(0编辑  收藏  举报