Nightmare
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 17 Accepted Submission(s) : 4
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Given the layout of the labyrinth and Ignatius' start position, please tell Ignatius whether he could get out of the labyrinth, if he could, output the minimum time that he has to use to find the exit of the labyrinth, else output -1.
Here are some rules:
1. We can assume the labyrinth is a 2 array.
2. Each minute, Ignatius could only get to one of the nearest area, and he should not walk out of the border, of course he could not walk on a wall, too.
3. If Ignatius get to the exit when the exploding time turns to 0, he can't get out of the labyrinth.
4. If Ignatius get to the area which contains Bomb-Rest-Equipment when the exploding time turns to 0, he can't use the equipment to reset the bomb.
5. A Bomb-Reset-Equipment can be used as many times as you wish, if it is needed, Ignatius can get to any areas in the labyrinth as many times as you wish.
6. The time to reset the exploding time can be ignore, in other words, if Ignatius get to an area which contain Bomb-Rest-Equipment, and the exploding time is larger than 0, the exploding time would be reset to 6.
Input
Each test case starts with two integers N and M(1<=N,Mm=8) which indicate the size of the labyrinth. Then N lines follow, each line contains M integers. The array indicates the layout of the labyrinth.
There are five integers which indicate the different type of area in the labyrinth:
0: The area is a wall, Ignatius should not walk on it.
1: The area contains nothing, Ignatius can walk on it.
2: Ignatius' start position, Ignatius starts his escape from this position.
3: The exit of the labyrinth, Ignatius' target position.
4: The area contains a Bomb-Reset-Equipment, Ignatius can delay the exploding time by walking to these areas.
Output
Sample Input
3 3 3 2 1 1 1 1 0 1 1 3 4 8 2 1 1 0 1 1 1 0 1 0 4 1 1 0 4 1 1 0 0 0 0 0 0 1 1 1 1 4 1 1 1 3 5 8 1 2 1 1 1 1 1 4 1 0 0 0 1 0 0 1 1 4 1 0 1 1 0 1 1 0 0 0 0 3 0 1 1 1 4 1 1 1 1 1
Sample Output
4 -1 13 代碼:0MS 首先要找最短路就要用的廣搜。 只能保證代碼的正確性,思路懂一點,但是換另一種方法做,就一直WA... 這道題和平時搜索題不同在於有炸彈時間重置點,所以並不是走過的點就不能再走,樣例3就很好的說明了這一點。 這就有一個問題了:怎麼判斷下一個點能不能走,因爲不能再用走過就標記的方法去判斷了。 一些人是判斷重置點只能去一次(明顯,再去時間也只能將時間重置爲6,而路徑加長)。 但是我感覺還是存在在兩個點之間跳,浪費時間的情況,所以我另外開了一個時間二維數組,如果在之後又要回到已經走過的點, 我就判斷剩餘時間是否比之前的大,廣搜已經得出之前到的一定路徑更短,要回到走過的點,一定要在之後可以走更遠,否則回 到該點一定不是最優的情況。於是判斷語句出來了:if(temp.time>T[temp.x][temp.y]) 就可以入隊。 #include <iostream> #include <stdio.h> #include <queue> #include <string.h> using namespace std; int map[20][20],Time[20][20]; int lx,ly,n,m; int dis[4][2]={1,0,0,1,-1,0,0,-1}; struct node { int x,y,time,run; //分別是:橫座標,縱座標,剩餘時間,走的步數。 }; int BFS(int fx,int fy,int time,int run) { int i,j; node t,temp; t.x=fx;t.y=fy;t.time=time;t.run=run; queue<node>Q; //起點入隊。 Q.push(t); memset(Time,0,sizeof(Time)); //時間表清空。 Time[t.x][t.y]=t.time; //起點的剩餘時間當然是6. while(!Q.empty()) { t=Q.front(); Q.pop(); if(t.time==0) continue; //因爲時間一到0炸彈就炸了,就算剛好到終點或重置點也炸了。所以就不用再去處理了。 else { if(map[t.x][t.y]==4) t.time=6; //如果到4,時間重置爲6. if(t.x==lx && t.y==ly) { return t.run; // 到達終點返回步數,廣搜最先到的一定是步數最少的。 } for(i=0;i<4;i++) //向四個方向走。 { temp.x=t.x+dis[i][0]; temp.y=t.y+dis[i][1]; temp.time=t.time-1; temp.run=t.run+1; if( temp.x>=0 && temp.x<n && temp.y>=0 && temp.y<m && map[temp.x][temp.y]!=0) //判斷是否可以走。 if(temp.time>Time[temp.x][temp.y]) //沒走過,當然成立;如果走過,就像上面說的,判斷是否會出現 { //更優解的可能。 Time[temp.x][temp.y]=temp.time; //對時間表更新。理由同上。 Q.push(temp); } } } } return -1; } int main() { int t,i,j; int fx,fy; while(scanf("%d",&t)!=EOF) { while(t--) { memset(map,0,sizeof(map)); scanf("%d%d",&n,&m); for(i=0;i<n;i++) for(j=0;j<m;j++) { scanf("%d",&map[i][j]); if(map[i][j]==2) {fx=i;fy=j;} //找起點。 if(map[i][j]==3) {lx=i;ly=j;} //找終點。 } i=BFS(fx,fy,6,0); printf("%d\n",i); } } return 0; }