(最优解法)46行代码AC_HDU1242 Rescue(DFS解法+BFS解法)
勵志用少的代碼做高效表達
Problem Description
Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is described as a N * M (N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs in the prison.
Angel’s friends want to save Angel. Their task is: approach Angel. We assume that “approach Angel” is to get to the position where Angel stays. When there’s a guard in the grid, we must kill him (or her?) to move into the grid. We assume that we moving up, down, right, left takes us 1 unit time, and killing a guard takes 1 unit time, too. And we are strong enough to kill all the guards.
You have to calculate the minimal time to approach Angel. (We can move only UP, DOWN, LEFT and RIGHT, to the neighbor grid within bound, of course.)
Input
First line contains two integers stand for N and M.
Then N lines follows, every line has M characters. “.” stands for road, “a” stands for Angel, and “r” stands for each of Angel’s friend.
Process to the end of the file.
Output
For each test case, your program should output a single integer, standing for the minimal time needed. If such a number does no exist, you should output a line containing “Poor ANGEL has to stay in the prison all his life.”
題目鏈接——>HDU-1242
分析與思考
題意:天使被魔鬼抓走了,他的一群朋友(是一群!!!)準備救他, 有可能碰到守衛(wèi),要想通過需要步數(shù)+2。求天使與其朋友之間最短步數(shù)。
如果救不出來,則需要輸出:“Poor ANGEL has to stay in the prison all his life.”
考慮到該死的天使有一群朋友, 因此我們需要將起點與終點互換,起點標記為天使的位置(因為天使只有一個),找到離他最近的朋友輸出即可。
可選用的算法有DFS或BFS。 我使用的是DFS求解。 BFS解法后續(xù)更新。 請持續(xù)關(guān)注~。
二更:
更新了BFS的解法, 其中DFS解法耗時78MS, BFS解法耗時15MS, 筆者查看了網(wǎng)上大部分的代碼,目前來講的最優(yōu)解,應(yīng)該就是基于BFS的算法了。
注意:在用BFS解題時,我們往往會覺得第一個入隊的’r’一定代表最短路(老慣性思維了,該死), 但本題的特殊點在于有’x’守衛(wèi),遇守衛(wèi)需+2步,因此在迭代時可能得不到最優(yōu)解,如這組數(shù)據(jù):
2 5
axxxr
…
正確答案是:6
錯誤答案是:7
雖然不考慮這種特殊情況的代碼,提交也可以AC。
但作為一個處女座程序猿,就想把代碼搞到完美~
解決辦法是:定義一個Min變量,有多條路時保存最小值即可。
網(wǎng)上很多的博客都忽略了這一點,大家在參考時一定要注意。 代碼二展示了正確的寬搜解法。
后續(xù)更新DFS+BFS原理講解, 請持續(xù)關(guān)注哦~
總結(jié):本題坑點較多, 需仔細理解題意才能保證不錯。
代碼1_DFS解法
#include<bits/stdc++.h> using namespace std; char a[210][210]; //迷宮地圖 int vis[210][210]; //標記地圖中某點是否走過 int n, m; //迷宮的行列大小 int startx, starty; //迷宮起點坐標 int Min = 999999999; //所用最小步數(shù) int Next[4][2] = { //方向數(shù)組 {1, 0}, //向上{-1, 0}, //向下 {0, 1}, //向右 {0, -1}}; //向左void dfs(int x, int y, int step) {//邊界條件:找到終點,更新最小值if(a[x][y] == 'r') { Min = min(step, Min);return;} //若不是終點,判斷下一步是否為障礙物,是否越界,是否已經(jīng)走過,若無,則走 if(a[x][y]=='.' || a[x][y]=='x' || a[x][y]=='a' ) { //1、判斷是否是障礙物 for(int i = 0; i < 4; i++) {int t1 = x + Next[i][0];int t2 = y + Next[i][1];if(t1<0 || t1>=n || t2<0 || t2>=m) continue; //2、是否越界if(!vis[t1][t2]) { //3、是否已經(jīng)走過 vis[t1][t2] = 1;if(a[x][y]=='x') dfs(t1, t2, step+2);else dfs(t1, t2, step+1);vis[t1][t2] = 0;}} } } int main() {ios::sync_with_stdio(false); while(cin>>n>>m) {Min = 999999999;memset(vis, 0, sizeof(vis));for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) {cin>>a[i][j];if(a[i][j] == 'a') { startx=i, starty=j; } //由于朋友有多個,因此記錄天使位置,找朋友 }dfs(startx, starty, 0);if(Min == 999999999) cout << "Poor ANGEL has to stay in the prison all his life." << endl; else cout << Min << endl;} return 0; }代碼2_BFS解法
#include<iostream> #include<cstring> #define Max 40100 using namespace std;struct List{int x; //橫坐標int y; //縱坐標int sum; //總步數(shù) };char a[210][210]; int vis[210][210];int Next[4][2] = {{1, 0},{-1, 0},{0,1},{0,-1}};int main() {ios::sync_with_stdio(false); int n, m; while(cin>>n>>m) {//初始化與定義變量 memset(vis, 0, sizeof(vis)); //每次循環(huán)vis數(shù)組都需初始化 int startx, starty; //起點的x、y坐標int Min = 999999999; //最后的輸出結(jié)果 bool flag = false; //終止循環(huán)的標記 //輸入 for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) {cin>>a[i][j];if(a[i][j] == 'a') startx=i, starty=j;} //隊列初始化int head=0, tail=0; //頭結(jié)點,尾結(jié)點 List l[Max];l[tail].x = startx;l[tail].y = starty;l[tail].sum = 0;tail++;vis[startx][starty] = 1;flag = 0; //標記是否到達目標點 //當(dāng)目標不為空時循環(huán) while(head < tail) { //如果尾指針小于等于頭指針,代表隊列中無元素,返回 for(int i = 0; i < 4; i++) {int tx = l[head].x + Next[i][0];int ty = l[head].y + Next[i][1]; //終止本次循環(huán)的三種條件: 越界、該點是障礙物、已經(jīng)被搜索過。 //1、若越界則返回 if(tx<0 || tx>=n || ty<1 || ty>=m) continue;//2、若沒被搜索過且該點不是障礙物,則: if(!vis[tx][ty]) if(a[tx][ty] != '#') {vis[tx][ty]=1;l[tail].x = tx;l[tail].y = ty;//如果是x,則走兩步 if(a[tx][ty] == 'x') l[tail].sum = l[head].sum+2; else l[tail].sum=l[head].sum+1;tail++; //每次循環(huán)后,tail都需自加 }if(a[tx][ty]=='r') //若等于r,則與Min比較,取較小值。 Min = min(l[tail-1].sum, Min);}head++; //每次循環(huán)都要丟棄頭部元素 }//輸出 if(Min == 999999999) cout << "Poor ANGEL has to stay in the prison all his life." << endl;else cout << Min << endl;} return 0; }這世界就是,一些人總在晝夜不停的努力,而另外一些人,起床就發(fā)現(xiàn)世界已經(jīng)變了。
總結(jié)
以上是生活随笔為你收集整理的(最优解法)46行代码AC_HDU1242 Rescue(DFS解法+BFS解法)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原理详解与标准解法——蓝桥杯_2016年
- 下一篇: 代码分析+原理图解——棋盘覆盖问题-分治