Time Limit: 2000MS | Memory Limit: 30000K | |
Total Submissions: 6767 | Accepted: 1546 |
Description
Input
Output
Sample Input
8 9 1 1 1 3 2 1 1 3 3 1 1 3 4 1 1 3 1 1 0 3 1 2 0 3 1 3 0 3 1 4 0 3 2 1 1 2 2 1 2 3 1 3 1 1 3 2 1 3 3 1 1 2 0 3 3 0 4 3 1 1.5 1.5 4 0 1 1 0 1 1 1 1 1 2 1 1 1 1 2 0 1 1.5 1.7 -1 -1
Sample Output
5 -1
题目大意:有一个迷宫,在迷宫中有墙与门
有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)最少要穿过多少条门
解题思路:将坐标系看成网络 则墙和门可以看做网络上的边 每个区域对应四条边
感想:这题有点坑 第一是Nemo 可能不在迷宫内 那样直接输出0 第二是用C++提交为WA 用G++提交AC 应该是和编译器的输入有关吧 建议大家在输入量不是很很大的情况下 都用G++ 因为G++比较稳定
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #define maxn 210 using namespace std; int n,m,maxx,maxy,ans,flag,tstep; int ex,ey; int mp[maxn][maxn]; int mpx[maxn][maxn]; int mpy[maxn][maxn]; int vis[maxn][maxn]; int sta[maxn*maxn]; int dx[4]={0,0,-1,1}; // up down left right int dy[4]={1,-1,0,0}; struct Node { int x,y; int step; friend bool operator <(Node x1,Node x2) // 优先队列 按经过的门的次数排序 { return x1.step>x2.step; } }cur,now; priority_queue<Node>q; bool isok(int u,int v,int dd) // 判断是否能走 要注意方向不同时 要判断不同额边 { int i,j; tstep=0; if(u+dx[dd]>maxx+1||u+dx[dd]<0||v+dy[dd]>maxy+1||v+dy[dd]<0||vis[u+dx[dd]][v+dy[dd]]) return false; if(dd==0) { if(mpx[u][v+dy[dd]]==2) return false; else if(mpx[u][v+dy[dd]]) tstep=1; } else if(dd==1) { if(mpx[u][v]==2) return false; else if(mpx[u][v]) tstep=1; } else if(dd==2) { if(mpy[u][v]==2) return false; else if(mpy[u][v]) tstep=1; } else { if(mpy[u+dx[dd]][v]==2) return false; else if(mpy[u+dx[dd]][v]) tstep=1; } return true; } bool bfs() { int i,xx,yy,cnt; while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); cur.x=0; cur.y=0; cur.step=0; vis[0][0]=1; q.push(cur); while(!q.empty()) { now=q.top(); xx=now.x; yy=now.y; cnt=now.step; if(xx==ex&&yy==ey) { ans=cnt; return true; } for(i=0;i<4;i++) { if(isok(xx,yy,i)) { cur.x=xx+dx[i]; cur.y=yy+dy[i]; cur.step=cnt+tstep; // 经过门则加1 不经过则加0 q.push(cur); vis[cur.x][cur.y]=1; } } q.pop(); } return false; } int main() { int i,j; int tx,ty,d,l; double t1,t2; char c; while(scanf("%d%d",&n,&m)) { if(n==-1&&m==-1) break; memset(mpx,0,sizeof(mpx)); memset(mpy,0,sizeof(mpy)); maxx=maxy=-1; for(i=1;i<=n;i++) { scanf("%d%d%d%d",&tx,&ty,&d,&l); if(d) { for(j=ty;j<ty+l;j++) { mpy[tx][j]=2; // 墙 } if(maxy<ty+l-1) maxy=ty+l-1; } else { for(j=tx;j<tx+l;j++) { mpx[j][ty]=2; } if(maxx<tx+l-1) maxx=tx+l-1; } } for(i=1;i<=m;i++) { scanf("%d%d%d",&tx,&ty,&d); if(d) { for(j=ty;j<ty+1;j++) { mpy[tx][j]=1; // 门 } } else { for(j=tx;j<tx+1;j++) { mpx[j][ty]=1; } } } scanf("%lf%lf",&t1,&t2); ex=int(t1); ey=int(t2); flag=ans=0; if(ex>maxx+1||ey>maxy+1||ex<0||ey<0) flag=1; if(flag||bfs()) printf("%d\n",ans); else printf("-1\n"); } return 0; }
附:其实这题poj上的数据有些是不严谨的比如
4 1 3 2 1 1 1 3 0 2 1 1 0 2 1 1 1 2 2 1 1 1.5 1.5
这个数据答案应该是0 而不是1 这个是小峰峰想到的 在此赞一个 O(∩_∩)O
这里贴一份严谨代码吧 不过在poj上过不了 因为他的数据答案是错的
就是把标记数组换成三维 搜索的时候多搜一层就OK了
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #define maxn 210 using namespace std; int n,m,maxx,maxy,ans,flag,tstep; int ex,ey; int mp[maxn][maxn]; int mpx[maxn][maxn]; int mpy[maxn][maxn]; int vis[maxn][maxn][4]; int sta[maxn*maxn]; int dx[4]={0,0,-1,1}; // up down left right int dy[4]={1,-1,0,0}; struct Node { int x,y; int step; friend bool operator <(Node x1,Node x2) // 优先队列 按经过的门的次数排序 { return x1.step>x2.step; } }cur,now; priority_queue<Node>q; bool isok(int u,int v,int dd) // 判断是否能走 要注意方向不同时 要判断不同额边 { int i,j; tstep=0; if(u+dx[dd]>maxx+1||u+dx[dd]<0||v+dy[dd]>maxy+1||v+dy[dd]<0||vis[u+dx[dd]][v+dy[dd]][dd]) return false; if(dd==0) { if(mpx[u][v+dy[dd]]==2) return false; else if(mpx[u][v+dy[dd]]) tstep=1; } else if(dd==1) { if(mpx[u][v]==2) return false; else if(mpx[u][v]) tstep=1; } else if(dd==2) { if(mpy[u][v]==2) return false; else if(mpy[u][v]) tstep=1; } else { if(mpy[u+dx[dd]][v]==2) return false; else if(mpy[u+dx[dd]][v]) tstep=1; } return true; } bool bfs() { int i,xx,yy,cnt,flag1,fstep; ans=100000000; while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); cur.x=0; cur.y=0; cur.step=0; flag1=0; q.push(cur); while(!q.empty()) { now=q.top(); xx=now.x; yy=now.y; cnt=now.step; if(xx==ex&&yy==ey) { flag1=1; fstep=cnt; if(ans>cnt) ans=cnt; } if(flag1) { if(cnt>fstep) return true; } for(i=0;i<4;i++) { if(isok(xx,yy,i)) { cur.x=xx+dx[i]; cur.y=yy+dy[i]; cur.step=cnt+tstep; // 经过门则加1 不经过则加0 q.push(cur); vis[cur.x][cur.y][i]=1; } } q.pop(); } return false; } int main() { int i,j; int tx,ty,d,l; double t1,t2; char c; while(scanf("%d%d",&n,&m)) { if(n==-1&&m==-1) break; memset(mpx,0,sizeof(mpx)); memset(mpy,0,sizeof(mpy)); maxx=maxy=-1; for(i=1;i<=n;i++) { scanf("%d%d%d%d",&tx,&ty,&d,&l); if(d) { for(j=ty;j<ty+l;j++) { mpy[tx][j]=2; // 墙 } if(maxy<ty+l-1) maxy=ty+l-1; } else { for(j=tx;j<tx+l;j++) { mpx[j][ty]=2; } if(maxx<tx+l-1) maxx=tx+l-1; } } for(i=1;i<=m;i++) { scanf("%d%d%d",&tx,&ty,&d); if(d) { for(j=ty;j<ty+1;j++) { mpy[tx][j]=1; // 门 } } else { for(j=tx;j<tx+1;j++) { mpx[j][ty]=1; } } } scanf("%lf%lf",&t1,&t2); ex=int(t1); ey=int(t2); flag=ans=0; if(ex>maxx+1||ey>maxy+1||ex<0||ey<0) flag=1; if(flag||bfs()) printf("%d\n",ans); else printf("-1\n"); } return 0; }