您的位置:首页 > 其它

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

2014-03-13 19:53 465 查看
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上那个很厉害的“小优学姐”的代码研究。(/article/1968904.html

  得到启发思路,从新写代码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;
}


  递归效率太低了,这次深刻体会~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: