割草机

割草机

时间限制:C/C++ 1秒,其他语言2
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

有一块n*m的地,每块地要么长满杂草('W'表示),要么是空地('G'表示),现在有一个人站在(1,1),面向(1,m),他可以按如下两种方式移动:

 

1、向面朝的方向移动一格,耗费1单位时间

2、向下移动一格,并反转面朝的方向(右变左,左变右),耗费1单位时间

现在他想知道清除所有的杂草最少需要多少单位时间(清除完杂草之后不用返回(1,1))

输入描述:

第一行n,m
接下来n行每行一个字符串表示矩阵。
n,m<=150

输出描述:

一行一个整数表示答案。

示例1

输入

4 5

GWGGW

GGWGG

GWGGG

WGGGG

输出

11

示例2

输入

3 3

GWW

WWW

WWG

输出

7

思路:一开始看这道题以为是bfs/dfs那类。。。但是后来又感觉想多了,这个方向是固定的,也就是说必须把这一行的草都割完才能继续,否则不可能向上走,就回不来了。那怎么让它都割完呢?就首先从【1,1】开始,到下一行之前需要保证你下去的位置在能割到所有草的地方。就比如:你现在所在这行只能向右面走,那你需要保证所有的草都在你右边,同理,在你去下一行的时候,你只能向左走,那你下去的位置就要保证所有的草都在你左边才可以。还有一些细节就是如果下边没草就不用往下走了之类的。。。

说起来,这个用bfs/dfs可能也行。。。我这么想有些麻烦了。。。比较笨的方法。。。

 

 

#include <bits/stdc++.h>

using namespace std;

 

int main()

{

    int n,m;

    char c[155][155];

    int a[155][2];

    cin>>n>>m;

    for(int i=0;i<n;i++)

    {

        cin>>c[i];

    }

    memset(a,-1,sizeof(a));//初始化为-1

    for(int i=0;i<n;i++)

    {

        for(int j=0;j<m;j++)

        {

            if(c[i][j]=='W'&&a[i][0]==-1)

            {

                a[i][0]=j+1;

                a[i][1]=j+1;

            }

            if(c[i][j]=='W')

            {

                a[i][1]=j+1;

            }

        }

    }//先将每一行第一个有草的位置和最后一个有草的位置记在一个二维数组中

    /*for(int i=0;i<n;i++)

    {

        printf("%d %d \n",a[i][0],a[i][1]);

    }*/

    int ans=1,sum=0;

    for(int i=0;i<n-1;i++)

    {

        if(i%2==0)//偶数情况

        {

            if(a[i][1]!=-1)//这行有草 这行方向固定向右

            {

                sum+=abs(a[i][1]-ans);

                ans=a[i][1];//每次都更新ans的值

                //printf("sum=%d ans=%d\n",sum,ans);

                if(ans<a[i+1][1])

                {//需要和下一行草的位置比较 下一行方向是固定向左的 要保证下一行所有的草都在ans左边

                    sum+=abs(a[i+1][1]-ans);

                    ans=a[i+1][1];

                    //printf("sum=%d ans=%d\n",sum,ans);

                }

            }

            else//没草 也要判断需不需要多走 要保证下一行所有的草都在ans左边

            {

                if(ans<a[i+1][1]&&a[i+1][0]!=-1)

                {

                    sum+=abs(ans-a[i+1][1]);

                    ans=a[i+1][1];

                    //printf("sum=%d ans=%d\n",sum,ans);

                }

            }

        }

        else//同偶数情况分析

        {

            if(a[i][1]!=-1)

            {

                sum+=abs(ans-a[i][0]);

                ans=a[i][0];

                //printf("sum=%d ans=%d\n",sum,ans);

                if(ans>a[i+1][0]&&a[i+1][0]!=-1)

                {

                    sum+=abs(ans-a[i+1][0]);

                    ans=a[i+1][0];

                    //printf("sum=%d ans=%d\n",sum,ans);

                }

            }

            else

            {

                if(ans>a[i+1][0]&&a[i+1][0]!=-1)

                {

                    sum+=abs(a[i+1][0]-ans);

                    ans=a[i+1][0];

                    //printf("sum=%d ans=%d\n",sum,ans);

                }

            }

        }

        sum++;

        //printf("**sum=%d ans=%d**\n",sum,ans);

    }//这个不包括最后一行情况

    for(int i=n-1;i>=0;i--)

    {

        if(a[i][0]==-1)

            sum--;

        else

            break;

    }//倒着往上看 如果后面没有草就不必往下走 sum--

    if(a[n-1][0]!=-1)

    {

        if(n%2==1)

        {

            sum+=abs(a[n-1][1]-ans);

        }

        else

        {

            sum+=abs(ans-a[n-1][0]);

        }

    }//最后一行单独看 分奇偶

    cout<<sum<<endl;

    return 0;

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值