1. 程式人生 > >HDU 1484 Basic wall maze (dfs + 記憶化)

HDU 1484 Basic wall maze (dfs + 記憶化)

Basic wall maze

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 168    Accepted Submission(s): 52
Special Judge


Problem Description In this problem you have to solve a very simple maze consisting of: 

1.a 6 by 6 grid of unit squares 
2.3 walls of length between 1 and 6 which are placed either horizontally or vertically to separate squares 
3.one start and one end marker 
A maze may look like this:



You have to find a shortest path between the square with the start marker and the square with the end marker. Only moves between adjacent grid squares are allowed; adjacent means that the grid squares share an edge and are not separated by a wall. It is not allowed to leave the grid.

Input The input consists of several test cases. Each test case consists of five lines: The first line contains the column and row number of the square with the start marker, the second line the column and row number of the square with the end marker. The third, fourth and fifth lines specify the locations of the three walls. The location of a wall is specified by either the position of its left end point followed by the position of its right end point (in case of a horizontal wall) or the position of its upper end point followed by the position of its lower end point (in case of a vertical wall). The position of a wall end point is given as the distance from the left side of the grid followed by the distance from the upper side of the grid. 

You may assume that the three walls don't intersect with each other, although they may touch at some grid corner, and that the wall endpoints are on the grid. Moreover, there will always be a valid path from the start marker to the end marker. Note that the sample input specifies the maze from the picture above. 

The last test case is followed by a line containing two zeros.

Output For each test case print a description of a shortest path from the start marker to the end marker. The description should specify the direction of every move ('N' for up, 'E' for right, 'S' for down and 'W' for left).

There can be more than one shortest path, in this case you can print any of them.

Sample Input 1 6 2 6 0 0 1 0 1 5 1 6 1 5 3 5 0 0
Sample Output NEEESWW 題意:給定一張地圖,並且給定起點和終點,求起點到終點的最短距離,地圖上有牆,與以往的題目不同的是,以往的題目障礙物都是在格子上,但是本題的障礙物牆是在格子與格子的邊界線上,所以在輸入的時候就要進行預處理下,將牆的位置轉化為相鄰格子的東西南北方向牆的狀態,所以使用了一個3為陣列來記錄地圖的資訊map[x][y][0]-map[x][y][3] 分別表示座標為x,y的格子的四個方向牆的情況,0為沒牆,1為有牆,然後一個dfs找到最短路,以及每個點的前驅節點,最後列印路徑。程式碼中的註釋很詳細。題目本身很簡單,就是程式碼寫起來有點麻煩。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <stack>

using namespace std;

const int MAX = 9,limit = 6,INF = 1000;
const int dirx[4]={0,-1,0,1},diry[4]={1,0,-1,0};

//map[x][y][0]-map[x][y][3] 分別表示座標為x,y的格子的四個方向牆的情況,0為沒牆,1為有牆
int map[MAX][MAX][4];
//pre[x][y][0]用來記錄x,y的前驅格子的x座標,pre[x][y][1]用來記錄x,y的前驅格子的y座標
int dist[MAX][MAX],pre[MAX][MAX][2];
int sx,sy,ex,ey,pax,pay,pbx,pby;
stack<char> st;

void init(){
	int i,j;

	for(i=0;i<MAX;++i){
		for(j=0;j<MAX;++j){
			dist[i][j] = INF;
			map[i][j][0] = map[i][j][1] = map[i][j][2] = map[i][j][3] = 0;
		}
	}
}

void dfs(int x,int y,int cnt){
	
	
	int i,tx,ty;

	for(i=0;i<4;++i){
		if(map[x][y][i]==1)continue;
		tx = x+dirx[i];
		ty = y+diry[i];
		if(tx<1 || ty<1 || tx>limit || ty>limit)continue;
		if(cnt+1>dist[tx][ty])continue;
		//更短就要更新,並且記錄前驅
		dist[tx][ty] = cnt;
		pre[tx][ty][0] = x;
		pre[tx][ty][1] = y;
		dfs(tx,ty,cnt+1);
	}
}

void Path(){
	int px,py,x,y;

	x = ex,y = ey;
	px = pre[x][y][0];
	py = pre[x][y][1];

	while(1){
		//判斷方向
		if(x==px){//x座標相同看y座標的情況
			if(py<y)st.push('E');
			else st.push('W');
		}else{//y座標相同看x座標的情況
			if(px<x)st.push('S');
			else st.push('N');
		}
		if(px==sx && py==sy)break;
		x = px;
		y = py;
		px = pre[x][y][0];
		py = pre[x][y][1];
	}

	while(!st.empty()){
		printf("%c",st.top());
		st.pop();
	}
	printf("\n");
}

int main(){
    //freopen("in.txt","r",stdin);
    //(author : CSDN iaccepted)
	int i,j;
	while(scanf("%d %d",&sy,&sx)){
		if(sx==0 && sy==0)break;
		scanf("%d %d",&ey,&ex);
		
		init();
		for(i=0;i<3;++i){
			scanf("%d %d %d %d",&pay,&pax,&pby,&pbx);
			if(pax==pbx){
				for(j=pay+1;j<=pby;++j){
					map[pax][j][3] = 1;
					map[pax+1][j][1] = 1;
				}
			}else{
				for(j=pax+1;j<=pbx;++j){
					map[j][pby][0] = 1;
					map[j][pby+1][2] = 1;
				}
			}
		}

		dfs(sx,sy,0);

		Path();
	}
		
    return 0;
}