(最优解法)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
分析與思考
題意:天使被魔鬼抓走了,他的一群朋友(是一群!!!)準備救他, 有可能碰到守衛,要想通過需要步數+2。求天使與其朋友之間最短步數。
如果救不出來,則需要輸出:“Poor ANGEL has to stay in the prison all his life.”
考慮到該死的天使有一群朋友, 因此我們需要將起點與終點互換,起點標記為天使的位置(因為天使只有一個),找到離他最近的朋友輸出即可。
可選用的算法有DFS或BFS。 我使用的是DFS求解。 BFS解法后續更新。 請持續關注~。
二更:
更新了BFS的解法, 其中DFS解法耗時78MS, BFS解法耗時15MS, 筆者查看了網上大部分的代碼,目前來講的最優解,應該就是基于BFS的算法了。
注意:在用BFS解題時,我們往往會覺得第一個入隊的’r’一定代表最短路(老慣性思維了,該死), 但本題的特殊點在于有’x’守衛,遇守衛需+2步,因此在迭代時可能得不到最優解,如這組數據:
2 5
axxxr
…
正確答案是:6
錯誤答案是:7
雖然不考慮這種特殊情況的代碼,提交也可以AC。
但作為一個處女座程序猿,就想把代碼搞到完美~
解決辦法是:定義一個Min變量,有多條路時保存最小值即可。
網上很多的博客都忽略了這一點,大家在參考時一定要注意。 代碼二展示了正確的寬搜解法。
后續更新DFS+BFS原理講解, 請持續關注哦~
總結:本題坑點較多, 需仔細理解題意才能保證不錯。
代碼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; //所用最小步數 int Next[4][2] = { //方向數組 {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;} //若不是終點,判斷下一步是否為障礙物,是否越界,是否已經走過,若無,則走 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、是否已經走過 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; //總步數 };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)); //每次循環vis數組都需初始化 int startx, starty; //起點的x、y坐標int Min = 999999999; //最后的輸出結果 bool flag = false; //終止循環的標記 //輸入 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; //頭結點,尾結點 List l[Max];l[tail].x = startx;l[tail].y = starty;l[tail].sum = 0;tail++;vis[startx][starty] = 1;flag = 0; //標記是否到達目標點 //當目標不為空時循環 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]; //終止本次循環的三種條件: 越界、該點是障礙物、已經被搜索過。 //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++; //每次循環后,tail都需自加 }if(a[tx][ty]=='r') //若等于r,則與Min比較,取較小值。 Min = min(l[tail-1].sum, Min);}head++; //每次循環都要丟棄頭部元素 }//輸出 if(Min == 999999999) cout << "Poor ANGEL has to stay in the prison all his life." << endl;else cout << Min << endl;} return 0; }這世界就是,一些人總在晝夜不停的努力,而另外一些人,起床就發現世界已經變了。
總結
以上是生活随笔為你收集整理的(最优解法)46行代码AC_HDU1242 Rescue(DFS解法+BFS解法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原理详解与标准解法——蓝桥杯_2016年
- 下一篇: 代码分析+原理图解——棋盘覆盖问题-分治