poj3083 Children of the Candy Corn dfs 和 bfs 的综合,终于AC了

2014-03-13

TLE后就把输入和输出全改成 scanf( ) 和 printf( ) 了,但还是超时。感觉是搜索最短路径时用的方法太慢了。下面是TLE的代码:

///2014.3.11 - 2014.3.13
///poj3083

#include <iostream>
#include <cstdio>
using namespace std;

int w,h;               ///记录迷宫的大小
char maze[50][50];     ///记录迷宫
int start_w,start_h;   ///记录迷宫的开始位置
int start_pre;         ///其前一步的相对于现在位置的方向,
                            ///0表示在右,1表示在上面,2表示在左边,3是下面
bool findmin;          ///标记有没有找到最短路
int step;

int next_w[4] = {1,0,-1,0};   ///方便走下一步
int next_h[4] = {0,-1,0,1};

void dfs(int h,int w,int pre,int l_r)
{
    step++;
    if( maze[h][w]=='E' ){
        return;
    }
    if( maze[h+next_h[(pre+l_r)%4] ][w+next_w[(pre+l_r)%4] ] !='#' ){
        dfs( h+next_h[(pre+l_r)%4], w+next_w[(pre+l_r)%4], (pre+l_r+2)%4,l_r);
    }
    else if( maze[h+next_h[(pre+l_r*2)%4] ][w+next_w[(pre+l_r*2)%4] ] !='#' ){
        dfs( h+next_h[(pre+l_r*2)%4], w+next_w[(pre+l_r*2)%4], (pre+l_r*2+2)%4,l_r);
    }
    else if( maze[h+next_h[(pre+l_r*3)%4] ][w+next_w[(pre+l_r*3)%4] ] !='#' ){
        dfs( h+next_h[(pre+l_r*3)%4], w+next_w[(pre+l_r*3)%4], (pre+l_r*3+2)%4,l_r);
    }
    else{
        dfs( h+next_h[pre], w+next_w[pre], (pre+2)%4,l_r);
    }
}

void bfs(int h,int w,int pre,int deep)
{
    step++;

    if( findmin ) return;
    if( maze[h][w]=='E' ){
        findmin = true;
        return;
    }
    if( deep==step ){
        return;
    }

    if( maze[h+next_h[(pre+1)%4] ][w+next_w[(pre+1)%4] ] !='#' ){
        bfs( h+next_h[(pre+1)%4], w+next_w[(pre+1)%4], (pre+1+2)%4,deep);
        step--;
    }
    if( maze[h+next_h[(pre+2)%4] ][w+next_w[(pre+2)%4] ] !='#' ){
        bfs( h+next_h[(pre+2)%4], w+next_w[(pre+2)%4], (pre+2+2)%4,deep);
        step--;
    }
    if( maze[h+next_h[(pre+3)%4] ][w+next_w[(pre+3)%4] ] !='#' ){
        bfs( h+next_h[(pre+3)%4], w+next_w[(pre+3)%4], (pre+3+2)%4,deep);
        step--;
    }
}

void init()
{
    char c;
    scanf("%d%d",&w,&h);
    scanf("%c",&c);
    for(int i=1 ; i<=h ; i++){
        for(int j=1 ; j<=w ; j++){
            scanf("%c",&c);
            maze[i][j] = c;
            if( c=='S' ){
                start_w = j;
                start_h = i;
                if( j==1 )
                    start_pre = 2;
                else if( j==w )
                    start_pre = 0;
                else if( i==1 )
                    start_pre = 1;
                else
                    start_pre = 3;
            }
        }
        scanf("%c",&c);
    }
    step = 0;
}

int main()
{
//    freopen("in","r",stdin);
//    freopen("out","w",stdout);

    int cas;
    scanf("%d",&cas);
    while( cas-- ){
        init();

        dfs(start_h,start_w,start_pre,3);
        printf("%d ",step);

        step = 0;
        dfs(start_h,start_w,start_pre,1);
        printf("%d ",step);

        findmin = false;
        int deep;
        for(deep=1 ; !findmin ; deep++){
            step = 0;
            bfs(start_h,start_w,start_pre,deep);
        }
        printf("%d\n",--deep);
    }
    return 0;
}

 2014-03-17

  这个题折磨了我好几天,知道自己的bfs方法太慢,但是自己太菜了,不知道怎么改。各种不甘心,所以上英语课时找出CSDN上那个很厉害的“小优学姐”的代码研究。(http://blog.csdn.net/lyy289065406/article/details/6647668

  得到启发思路,从新写代码A掉这一题,废话少说,上代码:

///2014.3.17
///poj3083

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int W,H;               ///记录迷宫的大小
char maze[50][50];     ///记录迷宫
int start_w,start_h;   ///记录迷宫的开始位置
int start_pre;         ///其前一步的相对于现在位置的方向,
                            ///0表示在右,1表示在上面,2表示在左边,3是下面
int step;

int next_w[4] = {1,0,-1,0};   ///方便走下一步
int next_h[4] = {0,-1,0,1};

void dfs(int h,int w,int pre,int l_r)  ///l_r变量决定优先左拐还是右拐
{
    step = 1; ///起点是第一步
    while( maze[h][w] != 'E' ){
        step++;
        if( maze[h+next_h[(pre+l_r)%4] ][w+next_w[(pre+l_r)%4] ] !='#' ){
            h = h+next_h[(pre+l_r)%4];
            w = w+next_w[(pre+l_r)%4];
            pre = (pre+l_r+2)%4;
        }
        else if( maze[h+next_h[(pre+l_r*2)%4] ][w+next_w[(pre+l_r*2)%4] ] !='#' ){
            h = h+next_h[(pre+l_r*2)%4];
            w = w+next_w[(pre+l_r*2)%4];
            pre = (pre+l_r*2+2)%4;
        }
        else if( maze[h+next_h[(pre+l_r*3)%4] ][w+next_w[(pre+l_r*3)%4] ] !='#' ){
            h = h+next_h[(pre+l_r*3)%4];
            w = w+next_w[(pre+l_r*3)%4];
            pre = (pre+l_r*3+2)%4;
        }
        else{
            h = h+next_h[pre];
            w = w+next_w[pre];
            pre = (pre+2)%4;
        }
    }
    printf("%d ",step);
}

void bfs(int h,int w)  ///建立一个搜索树,'E'的深度就是最少的步数
{
    int p,q;
    p=q=0;
    
    int h_queue[1650];     ///记录搜到的每一步的h坐标
    int w_queue[1650];     ///记录搜到的每一步的w坐标
    int deep_queue[1650];  ///记录搜到的每一步的深度

    bool visited[50][50];
    memset(visited,false,sizeof(bool)*50*50);
    
    h_queue[1] = h;
    w_queue[1] = w;
    deep_queue[1] = 1;
    p=0;
    q=1;

    while( p!=q ){
        p++;
        if( maze[ h_queue[p] ][ w_queue[p]+1 ]=='.' 
            && !visited[ h_queue[p] ][ w_queue[p]+1 ] 
            || maze[ h_queue[p] ][ w_queue[p]+1 ]=='E'){
            if(maze[ h_queue[p] ][ w_queue[p]+1 ]=='E'){
                printf("%d\n",deep_queue[p]+1 );
                break;
            }
            q++;
            visited[ h_queue[p] ][ w_queue[p]+1 ] = true;
            h_queue[q] = h_queue[p];
            w_queue[q] = w_queue[p]+1;
            deep_queue[q] = deep_queue[p]+1;
        }
        if( maze[ h_queue[p]+1 ][ w_queue[p] ]=='.' 
            && !visited[ h_queue[p]+1 ][ w_queue[p] ] 
            || maze[ h_queue[p]+1 ][ w_queue[p] ]=='E'){
            if(maze[ h_queue[p]+1 ][ w_queue[p] ]=='E'){
                printf("%d\n",deep_queue[p]+1 );
                break;
            }
            q++;
            visited[ h_queue[p]+1 ][ w_queue[p] ] = true;
            h_queue[q] = h_queue[p]+1;
            w_queue[q] = w_queue[p];
            deep_queue[q] = deep_queue[p]+1;
        }
        if( maze[ h_queue[p] ][ w_queue[p]-1 ]=='.' 
            && !visited[ h_queue[p] ][ w_queue[p]-1 ] 
            || maze[ h_queue[p] ][ w_queue[p]-1 ]=='E'){
            if(maze[ h_queue[p] ][ w_queue[p]-1 ]=='E'){
                printf("%d\n",deep_queue[p]+1 );
                break;
            }
            q++;
            visited[ h_queue[p] ][ w_queue[p]-1 ] = true;
            h_queue[q] = h_queue[p];
            w_queue[q] = w_queue[p]-1;
            deep_queue[q] = deep_queue[p]+1;
        }
        if( maze[ h_queue[p]-1 ][ w_queue[p] ]=='.' 
            && !visited[ h_queue[p]-1 ][ w_queue[p] ] 
            || maze[ h_queue[p]-1 ][ w_queue[p] ]=='E'){
            if(maze[ h_queue[p]-1 ][ w_queue[p] ]=='E'){
                printf("%d\n",deep_queue[p]+1 );
                break;
            }
            q++;
            visited[ h_queue[p]-1 ][ w_queue[p] ] = true;
            h_queue[q] = h_queue[p]-1;
            w_queue[q] = w_queue[p];
            deep_queue[q] = deep_queue[p]+1;
        }
    }
}

void init()
{
    char c;
    scanf("%d%d",&W,&H);
    scanf("%c",&c);
    for(int i=1 ; i<=H ; i++){    ///读入迷宫
        for(int j=1 ; j<=W ; j++){
            scanf("%c",&c);
            maze[i][j] = c;
            if( c=='S' ){      ///找到起点并设置起点信息
                start_w = j;
                start_h = i;
                if( j==1 )
                    start_pre = 2;
                else if( j==H )
                    start_pre = 0;
                else if( i==1 )
                    start_pre = 1;
                else
                    start_pre = 3;
            }
        }
        scanf("%c",&c);
    }
    step = 0;
}

int main()
{
    // freopen("in","r",stdin);
    // freopen("out","w",stdout);

    int cas;
    scanf("%d",&cas);
    while( cas-- ){
        init();  ///初始化工作
        dfs(start_h,start_w,start_pre,3); ///优先左拐
        dfs(start_h,start_w,start_pre,1); ///优先右拐
        bfs(start_h,start_w);  ///最短步数
    }
    return 0;
}

  递归效率太低了,这次深刻体会~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值