BDFZOI 拯救行动

难度:普及

题目类型:BFS

提交次数:4

涉及知识:BFS、优先队列

描述

公主被恶人抓走,被关押在牢房的某个地方。牢房用N*M (N, M <= 200)的矩阵来表示。矩阵中的每项可以代表道路(@)、墙壁(#)、和守卫(x)。 
英勇的骑士(r)决定孤身一人去拯救公主(a)。我们假设拯救成功的表示是“骑士到达了公主所在的位置”。由于在通往公主所在位置的道路中可能遇到守卫,骑士一旦遇到守卫,必须杀死守卫才能继续前进。 
现假设骑士可以向上、下、左、右四个方向移动,每移动一个位置需要1个单位时间,杀死一个守卫需要花费额外的1个单位时间。同时假设骑士足够强壮,有能力杀死所有的守卫。

给定牢房矩阵,公主、骑士和守卫在矩阵中的位置,请你计算拯救行动成功需要花费最短时间。

输入

第一行为一个整数S,表示输入的数据的组数(多组输入)

随后有S组数据,每组数据按如下格式输入 
1、两个整数代表N和M, (N, M <= 200). 
2、随后N行,每行有M个字符。"@"代表道路,"a"代表公主,"r"代表骑士,"x"代表守卫, "#"代表墙壁。输出如果拯救行动成功,输出一个整数,表示行动的最短时间。
如果不可能成功,输出"Impossible"样例输入

2
7 8
#@#####@
#@a#@@r@
#@@#x@@@
@@#@@#@#
#@@@##@@
@#@@@@@@
@@@@@@@@ 
13 40
@x@@##x@#x@x#xxxx##@#x@x@@#x#@#x#@@x@#@x
xx###x@x#@@##xx@@@#@x@@#x@xxx@@#x@#x@@x@
#@x#@x#x#@@##@@x#@xx#xxx@@x##@@@#@x@@x@x
@##x@@@x#xx#@@#xxxx#@@x@x@#@x@@@x@#@#x@#
@#xxxxx##@@x##x@xxx@@#x@x####@@@x#x##@#@
#xxx#@#x##xxxx@@#xx@@@x@xxx#@#xxx@x#####
#x@xxxx#@x@@@@##@x#xx#xxx@#xx#@#####x#@x
xx##@#@x##x##x#@x#@a#xx@##@#@##xx@#@@x@x
x#x#@x@#x#@##@xrx@x#xxxx@##x##xx#@#x@xx@
#x@@#@###x##x@x#@@#@@x@x@@xx@@@@##@@x@@x
x#xx@x###@xxx#@#x#@@###@#@##@x#@x@#@@#@@
#@#x@x#x#x###@x@@xxx####x@x##@x####xx#@x
#x#@x#x######@@#x@#xxxx#xx@@@#xx#x#####@

样例输出

13
7

代码:

 1 #include<iostream>
 2 #include<queue>
 3 #include<cstring>
 4 using namespace std;
 5 int s;
 6 int n, m;
 7 int dirx[4] = {1,-1,0,0};
 8 int diry[4] = {0,0,1,-1};
 9 struct node{
10     int x, y;
11     int step;
12     node(int xx, int yy, int ss): x(xx), y(yy), step(ss){}
13 };
14 
15 bool operator<(const node&a, const node&b){
16         return a.step>b.step;
17 } 
18 
19 priority_queue<node>q;
20 bool visited[205][205];
21 char a[205][205];
22 
23 int main(){
24     cin>>s;
25     while(s--){
26         cin>>n>>m;
27         while(!q.empty()) q.pop();
28         memset(visited, 0, sizeof(visited));
29         memset(a, 0, sizeof(a));
30         int i, j;
31         int flag = 0;
32         for(i = 1; i <= n; i++)
33             for(j = 1; j <= m; j++){
34                 cin>>a[i][j];
35                 if(a[i][j] == 'r'){
36                     q.push(node(i,j,0));
37                     visited[i][j] = true;
38                 }
39             }
40         while(!q.empty()){
41             node no = q.top();
42             q.pop();
43             if(a[no.x][no.y]=='a'){
44                 cout<<no.step<<endl;
45                 flag = 1;
46                 break;
47             }
48 //            cout<<no.x<<" "<<no.y<<endl;
49 //            cout<<a[no.x][no.y]<<endl;
50             for(i = 0; i < 4; i++){
51                 int nx = no.x+dirx[i];
52                 int ny = no.y+diry[i];
53                 if((a[nx][ny]=='@'||a[nx][ny]=='a')&&!visited[nx][ny]){
54                     q.push(node(nx,ny,no.step+1));
55                     visited[nx][ny] = true;
56                 }
57                 else if(a[nx][ny]=='x'&&!visited[nx][ny]){
58                     q.push(node(nx,ny,no.step+2));
59                     visited[nx][ny] = true;
60                 }
61             }
62         }
63         if(!flag) cout<<"Impossible"<<endl;
64     }
65     return 0;
66 }

备注:

 因为是带权图,变成加堆的BFS,跟dijkstra一个道理,看来我理解得还是不够深刻。

……

再次犯了同样的错误。自己都嫌弃自己了。

首先,发现程序什么都不输出(忘加impossible),发现拓展时就没把是a的情况设置成合法。。

然后,impossible的大小写问题。。这种细节。。

后来又有错,查了半天,尤其是上次犯过的初始化问题,还看了好几次。

结果还是老师告诉我。。visited数组清空了两次。。。a数组没清空。

智障。。

 运算符重载已经有点不太熟悉了。。优先队列是最大的优先级最大,小于号判断。所以是重载小于号。

原文地址:https://www.cnblogs.com/fangziyuan/p/6567024.html