1. 程式人生 > >nyoj-題目58-最少步數【DFS】

nyoj-題目58-最少步數【DFS】

最少步數

時間限制:3000 ms  |  記憶體限制:65535 KB 難度:4
描述

這有一個迷宮,有0~8行和0~8列:

 1,1,1,1,1,1,1,1,1
 1,0,0,1,0,0,1,0,1
 1,0,0,1,1,0,0,0,1
 1,0,1,0,1,1,0,1,1
 1,0,0,0,0,1,0,0,1
 1,1,0,1,0,1,0,0,1
 1,1,0,1,0,1,0,0,1
 1,1,0,1,0,0,0,0,1
 1,1,1,1,1,1,1,1,1

0表示道路,1表示牆。

現在輸入一個道路的座標作為起點,再如輸入一個道路的座標作為終點,問最少走幾步才能從起點到達終點?

(注:一步是指從一座標點走到其上下左右相鄰座標點,如:從(3,1)到(4,1)。)

輸入
第一行輸入一個整數n(0<n<=100),表示有n組測試資料;
隨後n行,每行有四個整數a,b,c,d(0<=a,b,c,d<=8)分別表示起點的行、列,終點的行、列。
輸出
輸出最少走幾步。
樣例輸入
2
3 1  5 7
3 1  6 7
樣例輸出
12
11

初學DFS,想法很菜,勿噴。。。談一下解其他迷宮題的思路,有的題可能沒有設邊界(不像這道題周圍都是牆 封閉的),這時候會有bug,可能程式找的解不是在區域內的路線,可能會出這個區域,這時候要多加個限制條件,讓 0 < 座標 < 行數、列數;或是設定map地圖陣列時,在原有的區域周圍都加上一堵牆,用牆圈起來,這樣也能達到效果

DFS解法:

#include<cstdio>  
#include<algorithm>  
#define Q 10000  
using namespace std;  
int x,y,ex,ey,ans;  
int dx[4]={-1,1,0,0};  
int dy[4]={0,0,-1,1};   // dx[4],dy[4] 是為了控制 上下左右 四個方向的   
int map[9][9]={ 1,1,1,1,1,1,1,1,1,  
                1,0,0,1,0,0,1,0,1,  
                1,0,0,1,1,0,0,0,1,  
                1,0,1,0,1,1,0,1,1,  
                1,0,0,0,0,1,0,0,1,  
                1,1,0,1,0,1,0,0,1,  
                1,1,0,1,0,1,0,0,1,  
                1,1,0,1,0,0,0,0,1,  
                1,1,1,1,1,1,1,1,1 };  
void DFS(int x,int y,int c)  //找到滿足條件的最優解   
{  
    if(x==ex&&y==ey)  
    {  
        if(c<ans)   // 判斷此時的 c 是否為最優解   
        {  
            ans=c;    
        }  
    }  
    else  
    {  
        for(int i=0;i<4;i++)  
        {  
            int nx=x+dx[i];  
            int ny=y+dy[i];  
            if(!map[nx][ny]&&c<ans-1)  // 限制此時的 c 比上一步的解 ans-1小   
            {  
                map[nx][ny]=1;  
                DFS(nx,ny,c+1);   // 這裡 c 還要加 1,這就可以解釋上面判斷要 a<ans-1 了   
                map[nx][ny]=0;   // 因為可能選擇一條路不通時,為下一條路的選擇,初始化該點  
            }  
        }  
    }  
}  
int main()  
{  
    int t;  
    scanf("%d",&t);  
    while(t--)  
    {  
        int c=0;  
        scanf("%d %d %d %d",&x,&y,&ex,&ey);  
        ans=Q;    // 這裡先給 ans 一個較大的值,要篩選 c   
        map[x][y]=1;  
        DFS(x,y,c);  
        printf("%d\n",ans);  
        map[x][y]=0;  // 為了不影響下一組資料的測試,初始化該點   
    }  
    return 0;  
}  

BFS解法:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int map[9][9]={ 1,1,1,1,1,1,1,1,1,
 				1,0,0,1,0,0,1,0,1,
 				1,0,0,1,1,0,0,0,1,
 				1,0,1,0,1,1,0,1,1,
				1,0,0,0,0,1,0,0,1,
 				1,1,0,1,0,1,0,0,1,
 				1,1,0,1,0,1,0,0,1,
 				1,1,0,1,0,0,0,0,1,
 				1,1,1,1,1,1,1,1,1 };
bool vis[9][9];
int kx,ky,ex,ey;
struct node
{
	int x,y,step;
};
int BFS()
{
	node s;
	s.x=kx,	s.y=ky,	s.step=0;
	vis[kx][ky]=1;
	queue<node> qu;
	qu.push(s);
	while( !qu.empty() )
	{
		node now=qu.front();
		qu.pop();
		if(now.x==ex&&now.y==ey)
			return now.step;
		for(int i=0;i<4;i++)
		{
			node next;
			next.x=now.x+dx[i];
			next.y=now.y+dy[i];
			next.step=now.step;
			if(!vis[next.x][next.y]&&!map[next.x][next.y])
			{
				vis[next.x][next.y]=1;
				next.step+=1;
				qu.push(next);
			}
		}
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(vis,0,sizeof(vis));
		scanf("%d %d %d %d",&kx,&ky,&ex,&ey);
		printf("%d\n",BFS());
	}
	return 0;
}