使用優先級隊列廣搜還是使用隊列廣搜
- 題目
hdu網址:http://acm.hdu.edu.cn/showproblem.php?pid=1253 - 我的解答
2.1使用優先級隊列的廣搜,很清楚,每次只擴展時間最短的那一個分支,一定能找到最短的那個,如果大於T輸出-1,否則輸出時間。然而優先級隊列耗時,主要是優先級隊列的維護。
/**
* > File Name: runproblem.cpp
* > Author: yyHaker
* > Created Time: 2017/6/10
* 使用優先級隊列超時
*/
#include<iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int K,A,B,C,T;
int maze[55][55][55];
int vis[55][55][55]; //保存是否被訪問狀態以及到達改點的時間
int d[6][3]={1,0,0,
-1,0,0,
0,1,0,
0,-1,0,
0,0,1,
0,0,-1};
struct node{
int a,b,c;
int time;
friend bool operator<(node n1,node n2){ //優先級隊列的排序準則
return n2.time<n1.time;
}
};
//起點(0,0,0)->(A-1,B-1,C-1)
int bfs(){
priority_queue<node> q;
node s;
s.a=0,s.b=0,s.c=0,s.time=0;
vis[s.a][s.b][s.c]=1;
q.push(s);
while(!q.empty()){
node t=q.top(); q.pop();
if(t.a==A-1&&t.b==B-1&&t.c==C-1){
return t.time;
}
if(t.time>T) return 0;
node nn;
for(int i=0;i<6;i++){
nn.a=t.a+d[i][0];
nn.b=t.b+d[i][1];
nn.c=t.c+d[i][2];
nn.time=t.time+1;
if(nn.a>=0&&nn.a<A&&nn.b>=0&&nn.b<B&&nn.c>=0&&nn.c<C&&maze[nn.a][nn.b][nn.c]==0){
if(!vis[nn.a][nn.b][nn.c]||(vis[nn.a][nn.b][nn.c]&&vis[nn.a][nn.b][nn.c]>nn.time)){ //訪問了的點可以被訪問,但是必須時間比以前短
q.push(nn);
vis[nn.a][nn.b][nn.c]=nn.time; //記錄時間
}
}
}
}
return 0;
}
int main(){
scanf("%d",&K);
while(K--){
scanf("%d%d%d%d",&A,&B,&C,&T);
for(int a=0;a<A;a++){
for(int b=0;b<B;b++){
for(int c=0;c<C;c++){
scanf("%d",&maze[a][b][c]);
}
}
}
//bfs
memset(vis,0,sizeof(vis));
int ans=bfs();
//printf("%d\n",ans);
if(ans==0||ans>T) printf("-1\n");
else printf("%d\n",ans);
}
}
2.2使用普通隊列的廣搜,擴展所有可能的分支,到達終點時即可得到最短時間。
/**
* > File Name: runproblem_queue.cpp
* > Author: yyHaker
* > Created Time: 2017/6/10
*
* 不使用優先級隊列就ac了
*/
#include<iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int K,A,B,C,T;
int maze[55][55][55];
int vis[55][55][55]; //保存是否被訪問狀態以及到達改點的時間
int d[6][3]={1,0,0,
-1,0,0,
0,1,0,
0,-1,0,
0,0,1,
0,0,-1};
struct node{
int a,b,c;
int time;
friend bool operator<(node n1,node n2){ //優先級隊列的排序準則
return n2.time<n1.time;
}
};
//起點(0,0,0)->(A-1,B-1,C-1)
int bfs(){
queue<node> q;
node s;
s.a=0,s.b=0,s.c=0,s.time=0;
vis[s.a][s.b][s.c]=1;
q.push(s);
while(!q.empty()){
node t=q.front(); q.pop();
if(t.a==A-1&&t.b==B-1&&t.c==C-1){
return t.time;
}
//if(t.time>T) return 0;
node nn;
for(int i=0;i<6;i++){
nn.a=t.a+d[i][0];
nn.b=t.b+d[i][1];
nn.c=t.c+d[i][2];
nn.time=t.time+1;
if(nn.a>=0&&nn.a<A&&nn.b>=0&&nn.b<B&&nn.c>=0&&nn.c<C&&maze[nn.a][nn.b][nn.c]==0&&nn.time<=T){
if(!vis[nn.a][nn.b][nn.c]||(vis[nn.a][nn.b][nn.c]&&vis[nn.a][nn.b][nn.c]>nn.time)){ //訪問了的點可以被訪問,但是必須時間比以前短
q.push(nn);
vis[nn.a][nn.b][nn.c]=nn.time; //記錄時間
}
}
}
}
return 0;
}
int main(){
scanf("%d",&K);
while(K--){
scanf("%d%d%d%d",&A,&B,&C,&T);
for(int a=0;a<A;a++){
for(int b=0;b<B;b++){
for(int c=0;c<C;c++){
scanf("%d",&maze[a][b][c]);
}
}
}
//bfs
memset(vis,0,sizeof(vis));
int ans=bfs();
//printf("%d\n",ans);
if(ans==0||ans>T) printf("-1\n");
else printf("%d\n",ans);
}
}