难度:普及
题目类型: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数组没清空。
智障。。
运算符重载已经有点不太熟悉了。。优先队列是最大的优先级最大,小于号判断。所以是重载小于号。