POJ 2049 Finding Nemo BFS 三维数组存状态, 优先队列优化时间与空间
题目大意:有一个迷宫,在迷宫中有墙与门
有m道墙,每一道墙表示为(x,y,d,t)
x,y表示墙的起始坐标
d为0即向右t个单位,都是墙
d为1即向上t个单位,都是墙
有n道门,每一道门表示为(x,y,d)
x,y表示门的起始坐标
d为0即向右一个单位表示门
d为1即向上一个单位表示门
再给出你起点的位置(f1,f2),并保证这个点的位置不会再墙或者门中,为起点到(0,0)最少要穿过多少条门
周围的其他地方都是空地,在空地上行走是不浪费步数的。
思路是:
可以从终点去bfs找到达(0,0)点的最短路,遇到门就步数加1 ,遇到空地 步数不变位置改变,
遇到墙不可以行走了。
对于每一个点小方格都可以用左下角(x,y)的坐标来表示,然后用四个变量分别表示该空格的四周的状态,(用0,1,2,3分别表示左上右下) 每个空格四周的状态又分为(0,1,INF,分别表示空地,有门,有墙)
刚开始用普通的队列,边界条件没判断好,出现了MLE,改用priority_queue ,之后WA,结果是符号的重载,重载反了,最后交C++,wa,然后改用G++交就ac。
注意,对于ma[][][]的坐标的选取问题,一定要画图进行选取,否则会取颠倒
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define INF 0x3f3f3f3f
#define bug puts("*****************")
using namespace std;
const int NN=220;
int ma[NN][NN][4];
int vis[NN][NN];
int n,m,Min;
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
struct node{
int x,y,step;
node(){};
node (int a,int b,int c){
x=a;
y=b;
step=c;
}
friend bool operator <(node p1,node p2){
return p1.step>p2.step; ///认清重载符合
}
};
priority_queue<node,vector<node>,less<node> >Q;
int judge(int x,int y){
if(x<0||y<0||x>199||y>199) return 0;
return 1;
}
void BFS(int x,int y){
while(!Q.empty()) Q.pop();
node no,temp;
vis[x][y]=1;
no.x=x;
no.y=y;
no.step=0;
Q.push(no);
while(!Q.empty()){
no=Q.top();
Q.pop();
// cout<<no.x<<" "<<no.y<<endl;
if(no.x==0&&no.y==0){
Min=min(Min,no.step);
break;
}
if(no.step>=Min) continue;
// cout<<no.step<<endl;
for(int i=0;i<4;i++){ ///四周
if(ma[no.x][no.y][i]==1){
temp.x=no.x+dx[i]; ///dx[i]方向与i对应
temp.y=no.y+dy[i];
temp.step=no.step+1;
if(!vis[temp.x][temp.y]&&judge(temp.x,temp.y)){ ///遇到门的情况
vis[temp.x][temp.y]=1;
// cout<<temp.x<<" "<<temp.y<<endl;
Q.push(temp);
}
}
else if(ma[no.x][no.y][i]==0){ ///空地情况
temp.x=no.x+dx[i];
temp.y=no.y+dy[i];
temp.step=no.step;
if(!vis[temp.x][temp.y]&&judge(temp.x,temp.y)){
vis[temp.x][temp.y]=1;
Q.push(temp);
}
}
}
}
// cout<<Min<<endl;
printf(Min==INF?"-1
":"%d
",Min);
}
int main(){
int u,v,d,t;
// Q.push(node(1,2,1));
//
// Q.push(node(2,1,4));
// Q.push(node(2,4,7));
// cout<<(Q.top()).step<<endl;
while(~scanf("%d%d",&n,&m)&&(!(n+1==0&&m+1==0))){
memset(ma,0,sizeof(ma));
memset(vis,0,sizeof(vis));
Min=INF;
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&u,&v,&d,&t);
if(d==0){
for(int j=0;j<t;j++) ma[u+j][v][3]=ma[u+j][v-1][1]=INF; ///刚开始方向写反了
//cout<<u<<" "<<v<<" "<<u-1<<" "<<endl;
}
else{
for(int j=0;j<t;j++) ma[u][v+j][0]=ma[u-1][v+j][2]=INF;
}
}
for(int j=1;j<=m;j++){
scanf("%d%d%d",&u,&v,&d);
if(d==0) ma[u][v][3]=ma[u][v-1][1]=1;
else ma[u][v][0]=ma[u-1][v][2]=1;
}
double x,y;
scanf("%lf%lf",&x,&y);
int xsta=(int)x;
int ysta=(int)y;
if(!judge(xsta,ysta))
puts("0");
else{
BFS(xsta,ysta);
}
}
return 0;
}
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 创建动态数组
- 下一篇: C语言动态数组原理及实现
