网易18实习生网测题--吃豆子

来源:互联网 发布:百度搜索软件 编辑:程序博客网 时间:2024/05/17 01:34

网易18实习生网测题–吃豆子

题目是酱滴,你是一个吃豆人,输入下面的参数,其中E表示没豆,W表示有豆。有三条规则:

4 5
EEWEW
EEWEE
EWEEE
EEEEW

  • 初始化的时候你在左上角,面向右边,而且保证这里没有豆(意思是不存在一个图只有左上角有豆这样不需要动你就赢了嘛)
  • 每一次你有两个移动选择,可以往面向的方向走一步
  • 也可以往下面走一步,但这样你面向的方向要反过来

最后问你吃完所有豆子的最短路径。图的最大格数是150*150。

DFS法

我们敲代码,就是一把梭。这不是要问最短路吗,BFS写起来麻烦,后面还有两道题呢。那我赶紧写一个DFS试试。

void dfs(int pn, int pm, int dir, int steps, int now){    if(pn >=n || pm >= m)    {        return;    }    if(graphs[pn][pm] == 'W')        now++;    steps++;    if(now >=target)    {        if(steps > answer)            answer = steps;        return;    }    if(dir ==0)    {        dfs(pn,pm-1,0,steps,now);        dfs(pn+1,pm,1,steps,now);    }    else    {        dfs(pn,pm+1,1,steps,now);        dfs(pn+1,pm,-1,steps,now);    }}

每次历遍一次,要不往当前方向走一步,然后dfs,要不下走一步,转向,继续dfs。结束条件是出了边界,或者吃完所有豆子了。登登登,一提交,过了50%样例,后面的超时了……

这就很懵了。我当时也没想到好的剪枝的方法。也没考虑一下复杂度。之后我找到有人说

通常DFS和BFS复杂度大约均为:系数*状态数^层数
通常此数最多为1亿就八成爆掉

哦,意思是大概是2^150嘛……得,老老实实找规律。

O(n)的解法

看起来比较简单哈,其实有一个模拟的思想在里面的。根据题意我们可以知道,其实吃豆子是有规律的,每次都必须吃完这一行的才能往下走,而且往下走的时候,还必须满足能吃完下面一行的要求。所以我用pm指示当前豆子位于的列位置,历遍所有行。依据以下步骤:
1. 如果这一行没有豆子,我们就直接跳下一行
2. 先把指针指到能保证吃完这一行的位置(如果面向左边,指针要走到这一行的最右边的豆子那里;如果面向右边,就要走到最左边的豆子那里。),计算需要步数。
3. 吃完这一行(就是如果是面左,就走到最左的豆子那里;反之亦然),计算步数。
4. 走下一行,转方向,重复1

额外情况是,如果都没有豆子,输出0就可以了,根本不用走。这是40%和50%case test夹着的那个test case的情况。

看起来比较清晰的步骤,其实自己做起来不够熟练,所以一些细节都不够周全,拖了很久,要练要练啊。其实考虑清楚这个清晰的步骤之后,写起来就很快了。

#include <iostream>#include <cstdio>using namespace std;char graphs[150][150];int target;int n,m;int l[150];int r[150];int main(){    //freopen("1.in","r",stdin);    target = 0;    cin >> n >> m;    for(int i = 0; i < n; i++)    {        l[i]=r[i]=-1;        bool isl = true;        for(int j = 0; j < m; j++)        {            cin >> graphs[i][j];            if(graphs[i][j] == 'W')            {                if(isl)                {                    l[i]=j;                    isl=false;                }                r[i]=j;                //cout<<l[i]<<r[i]<<endl;                target++;            }        }    }    if(target == 0)    {        cout << 0 << endl;        return 0;    }    int dire = 1;    int ans = 0;    int pm=0;    bool flag =true;    for(int i =0; i<n; i++)    {        if(l[i] < 0)        {            dire = -dire;            continue;        }        if(flag)        {            ans += r[i]-pm;            pm=r[i];            flag = false;            dire = -dire;            continue;        }        if(dire > 0)        {            if(pm > l[i])            {                ans += pm - l[i] + r[i] - l[i];                pm=r[i];            }            else            {                ans += r[i]-pm;                pm=r[i];            }            dire = -dire;        }        else        {            if(pm < r[i])            {                ans += r[i]-pm + r[i]-l[i];                pm=l[i];            }            else            {                ans += pm-l[i];                pm=l[i];            }            dire = -dire;        }    }    cout << ans+n-1 << endl;    return 0;}

登登,这样就肯定能过了,毕竟输入的复杂度都是O(n*m)了,所以必须能过啊。

0 0