XJOI 3585 The rescue plan 营救计划 题解
英文
Time Limit:1s Memory Limit:256M
Description
Given a n*m map.A “Mengxin” is trapped.You are the one to rescue him.In the map,there are some guards,you must defeat the guards to get your way.Defeat one guard takes 1 min,move one step takes 1 min,each step you can only take one of 4 directions(up,down,left,right).Please tell us the least time you cost to rescue the guy.
Input
The first line contains two integers n,m
The next n lines,each line input m characters represent the map. 1<=n,m<=200
‘@’ is your position
‘#’ is obstacle
‘.’ means there is a way you can go
‘G’ means guard
‘M’ means the position of “Mengxin”.
Output
If you can save this guy,output the least time you cost,else,output “You can’t save Mengxin”
Sample Input1
7 8 #.#####. #.M#..@. #..#G... ..#..#.# #...##.. .#...... ........Sample Output1
13
Sample Input2
2 2 M. G@?Sample Output2
2
中文
時間:1s 空間:128M
題目描述:
在一個n?m的迷宮里,有一個萌新被困住了,你作為一個久經碼場的戰士,決定去營救萌新。地圖中還會有一些守衛,你必須打敗守衛才能通過守衛所在的位置,打敗守衛需要花費1分鐘,移動一步需要花費一分鐘,每次你只能往上下左右某個方向移動一步。問你最少需要花費多少時間才能救到萌新。
輸入格式:
第一行輸入兩個整數 n,m
接下來n行每行輸入m個字符
‘#’代表障礙物,無法直接通過
‘.’代表空地,可以直接通過
‘G’代表守衛,你需要打敗他才能通過
‘M’代表萌新所在的位置
‘@’表示你所在的位置
輸出格式:
如果可以營救到萌新,就輸出最少需要花費的分鐘數
如果不可以,輸出“You can’t save Mengxin”
樣例輸入1:
7 8 #.#####. #.M#..@. #..#G... ..#..#.# #...##.. .#...... ........樣例輸出1:
13
樣例輸入2:
2 2 M. G@樣例輸出2:
2
約定:
1<=n,m<=200
注意:
以上輸入樣例中,用到的代碼片不是代碼,只是為了方便表示,謝謝。
提示:
這道題求的是最優解,很容易就想到廣度優先搜索(又稱寬度優先搜,BFS),最先在隊列里遇到的答案一定就是最優解了。廣度優先搜索用隊列實現,用隊列的left來擴展right來維持搜索。但還有一些小困難,比如打敗守衛要1分鐘的問題。如何解決呢?我們可以假設我們去營救她時,擁有一個技能可以秒殺有守衛,這個技能要蓄力1分鐘,這是不是好理解一些呢?如果單純的認為經過守衛的點耗時2min,博主認為第一個掃到的終點不一定是最優解(個人觀點,未經嘗試)。請看代碼中的注解吧。具體代碼如下:
代碼:
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <algorithm> #define N 200 using namespace std ; struct mrz {int x , y , z ;//x,y還是表示坐標,z表示到該坐標時的時間bool jn ;//jn時技能是否蓄力。初始條件是jn=0,當在原地停留1min后,jn=1,打打掉守衛后,jn=0; //我們不用當心蓄力后還不打,卻繞路的問題,因為這肯定不是最優解。如果蓄力后,繞路以后再打,也是可以的,不影響答案 } p [ N * N + 1 ] ; int x_c , y_c , x_z , y_z , n , m , l = 1 , r = 1 , ans = N*N*N ; int mp [ N + 1 ] [ N + 1 ] ;//查看地圖上的點是否走過 bool pd_a ( int k1 , int k2 )//判斷是否達到目標 {if ( k1 == x_z && k2 == y_z ) return true ;else return false ; } bool pd_b ( int k1 , int k2 )//判斷該點是否可以走 {if ( k1 >= 1 && k1 <= n && k2 >= 1 && k2 <= m && mp [ k1 ] [ k2 ] != 0 ) return true ;else return false ; } int main ( ) {scanf ( "%d%d" , & n , & m ) ;char c ;memset ( p , 0 , sizeof ( p ) ) ;memset ( mp , 0 , sizeof ( mp ) ) ;for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= m ; j ++)//生成地圖{cin >> c ;if ( c == '.' || c == 'M' ) mp [ i ] [ j ] = 1 ;if ( c == 'M' ){x_z = i ;y_z = j ;}if ( c == '@' ){x_c = i ;y_c = j ;}if ( c == 'G' ) mp [ i ] [ j ] = 2 ;}p [ 1 ] . x = x_c ;p [ 1 ] . y = y_c ;while ( l <= r){ // cout << p [ l ] . x << " " << p [ l ] . y << " " << p [ l ] . z << endl ; // for ( int i = 1 ; i <= n ; i ++ ) // { // for ( int j = 1 ; j <= m ; j ++ ) cout << mp [ i ] [ j ] ; // cout << endl ; // } // system ( "pause" ) ; // 以上代碼可以調時使用if ( pd_b ( p [ l ] . x + 1 , p [ l ] . y ) == true ){r ++ ;if ( mp [ p [ l ] . x + 1 ] [ p [ l ] . y ] == 1 ){ //最正常的情況,走空地p [ r ] . x = p [ l ] . x + 1 ;p [ r ] . y = p [ l ] . y ;p [ r ] . z = p [ l ] . z + 1 ;p [ r ] . jn = p [ l ] . jn ;mp [ p [ r ] . x ] [ p [ r ] . y ] = 0 ;} else{if ( p [ l ] . jn == 0 ){ //前方有守衛,還未蓄力p [ r ] . x = p [ l ] . x ;p [ r ] . y = p [ l ] . y ;//原地不動p [ r ] . z = p [ l ] . z + 1 ;//耗時1minp [ r ] . jn = 1 ;//蓄力} else{//前方有守衛,蓄力完成p [ r ] . x = p [ l ] . x + 1 ;p [ r ] . y = p [ l ] . y ;p [ r ] . z = p [ l ] . z + 1 ;mp [ p [ r ] . x ] [ p [ r ] . y ] = 0 ;p [ r ] . jn = 0 ;}}if ( pd_a ( p [ r ] . x , p [ r ] . y ) == true && p [ r ] . z < ans ){ans = p [ r ] . z ;} //判斷答案}//以下是其他方向。廣搜代碼雖長,但大同小異。if ( pd_b ( p [ l ] . x - 1 , p [ l ] . y ) == true ){r ++ ;if ( mp [ p [ l ] . x - 1 ] [ p [ l ] . y ] == 1 ){p [ r ] . x = p [ l ] . x - 1 ;p [ r ] . y = p [ l ] . y ;p [ r ] . z = p [ l ] . z + 1 ;p [ r ] . jn = p [ l ] . jn ;mp [ p [ r ] . x ] [ p [ r ] . y ] = 0 ;} else{if ( p [ l ] . jn == 0 ){p [ r ] . x = p [ l ] . x ;p [ r ] . y = p [ l ] . y ;p [ r ] . z = p [ l ] . z + 1 ;p [ r ] . jn = 1 ;} else{p [ r ] . x = p [ l ] . x - 1 ;p [ r ] . y = p [ l ] . y ;p [ r ] . z = p [ l ] . z + 1 ;mp [ p [ r ] . x ] [ p [ r ] . y ] = 0 ;p [ r ] . jn = 0 ;}}if ( pd_a ( p [ r ] . x , p [ r ] . y ) == true && p [ r ] . z < ans ){ans = p [ r ] . z ;}}if ( pd_b ( p [ l ] . x , p [ l ] . y + 1 ) == true ){r ++ ;if ( mp [ p [ l ] . x ] [ p [ l ] . y + 1 ] == 1 ){p [ r ] . x = p [ l ] . x ;p [ r ] . y = p [ l ] . y + 1 ;p [ r ] . z = p [ l ] . z + 1 ;p [ r ] . jn = p [ l ] . jn ;mp [ p [ r ] . x ] [ p [ r ] . y ] = 0 ;} else{if ( p [ l ] . jn == 0 ){p [ r ] . x = p [ l ] . x ;p [ r ] . y = p [ l ] . y ;p [ r ] . z = p [ l ] . z + 1 ;p [ r ] . jn = 1 ;} else{p [ r ] . x = p [ l ] . x ;p [ r ] . y = p [ l ] . y + 1 ;p [ r ] . z = p [ l ] . z + 1 ;mp [ p [ r ] . x ] [ p [ r ] . y ] = 0 ;p [ r ] . jn = 0 ;}}if ( pd_a ( p [ r ] . x , p [ r ] . y ) == true && p [ r ] . z < ans ){ans = p [ r ] . z ;}}if ( pd_b ( p [ l ] . x , p [ l ] . y - 1 ) == true ){r ++ ;if ( mp [ p [ l ] . x ] [ p [ l ] . y - 1 ] == 1 ){p [ r ] . x = p [ l ] . x ;p [ r ] . y = p [ l ] . y - 1 ;p [ r ] . z = p [ l ] . z + 1 ;p [ r ] . jn = p [ l ] . jn ;mp [ p [ r ] . x ] [ p [ r ] . y ] = 0 ;} else{if ( p [ l ] . jn == 0 ){p [ r ] . x = p [ l ] . x ;p [ r ] . y = p [ l ] . y ;p [ r ] . z = p [ l ] . z + 1 ;p [ r ] . jn = 1 ;} else{p [ r ] . x = p [ l ] . x ;p [ r ] . y = p [ l ] . y - 1 ;p [ r ] . z = p [ l ] . z + 1 ;mp [ p [ r ] . x ] [ p [ r ] . y ] = 0 ;p [ r ] . jn = 0 ;}}if ( pd_a ( p [ r ] . x , p [ r ] . y ) == true && p [ r ] . z < ans ){ans = p [ r ] . z ;}}l ++ ;}if ( ans == N * N * N ) cout << "You can't save Mengxin" ;//還有不能營救的情況else cout << ans ;return 0 ; }相關鏈接:
XJOI 題解小全:
https://blog.csdn.net/zj_mrz/article/details/80949787
XJOI 3330 Knight moving 騎士出行 題解:
https://blog.csdn.net/zj_mrz/article/details/81031135
XJOI 3393 序列 題解:
https://blog.csdn.net/zj_mrz/article/details/80948621
XJOI 3404 刷油漆 題解:
https://blog.csdn.net/zj_mrz/article/details/80949407
轉載于:https://www.cnblogs.com/zj-mrz/p/10122469.html
總結
以上是生活随笔為你收集整理的XJOI 3585 The rescue plan 营救计划 题解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 戚继光抗日战争屡立战功抗击日本侵略
- 下一篇: 定时器里面的作用域问题