->题目请戳这里<-
题目大意:二维坐标平面内给m个墙,n个门,每个墙4个参数:x,y,d,t。(x,y)为墙最左/下点坐标,d表示墙的姿势,d = 1表示墙是竖着的,即平行于y轴,d=0表示墙水平的,墙的厚度不计。每个门3个参数:x,y,d,意义与墙相同,门的长度默认1。墙的范围1-199(此处乃大坑,说了都是泪啊啊。。。)。现在给你一个坐标(f1,f2),求从(0,0)点到给定点至少要过几个门。除了给定的墙和门,其他都是空地。
题目分析:题意很明白,算法很清楚,bfs。这题算是一道比较不错的搜索题,如果没有那个大坑的话。因为这个题要自己把地图构造出来。构造的思路是这样的:首先将所有的边缩成点,我是将所有的横边往左端点缩,所有的竖边往上端点缩。这样每个点有2个状态的边:横边和竖边。每条边有3个状态:0表示空地,1表示墙,2表示门。判重也比较简单,直接开3维数组判重就可以了。这样我们就可以搜了,要用到优先队列。
详情请见代码:
#include <iostream> #include<cstdio> #include<cstring> #include<queue> #include<cmath> using namespace std; const int N = 205; int map[N][N][2];//将门和墙缩成左上角一个点, //所以每个点用2个状态标识,0表示水平,1表示竖直, //每个状态用3个值表示具体状态,0表示什么都没有 //1表示墙,2表示门 bool flag[N][N][2];//判重 int m,n; int si,sj; int dx[] = {1,-1,0,0}; int dy[] = {0,0,1,-1}; struct node { int i,j,door; friend bool operator < (struct node a,struct node b) { return a.door > b.door; } }s,now; //queue<node>lcm; priority_queue<node>lcm; void bfs() { while(!lcm.empty()) lcm.pop(); s.door = 0; s.i = si; s.j = sj; lcm.push(s); while(!lcm.empty()) { //now = lcm.front(); now = lcm.top(); //printf("%d %d\n",now.i,now.j); //system("pause"); lcm.pop(); if(map[now.i][now.j][0] != 1)//可以向上走 { if(!flag[now.i][now.j][0]) { flag[now.i][now.j][0] = 1; if(map[now.i][now.j][0] == 2) s.door = now.door + 1; else s.door = now.door; s.i = now.i; s.j = now.j + 1; if(s.i == 0 && s.j == 0) { printf("%d\n",s.door); return; } if(s.i >= 0 && s.j >= 0 && s.i <= 202 && s.j <= 202) lcm.push(s); } } if(map[now.i][now.j][1] != 1)//可以向left走 { if(!flag[now.i][now.j][1]) { flag[now.i][now.j][1] = 1; if(map[now.i][now.j][1] == 2) s.door = now.door + 1; else s.door = now.door; s.i = now.i - 1; s.j = now.j; if(s.i == 0 && s.j == 0) { printf("%d\n",s.door); return; } if(s.i >= 0 && s.j >= 0 && s.i <= 202 && s.j <= 202) lcm.push(s); } } if(map[now.i + 1][now.j][1] != 1)//right { if(!flag[now.i + 1][now.j][1]) { flag[now.i + 1][now.j][1] = 1; if(map[now.i + 1][now.j][1] == 2) s.door = now.door + 1; else s.door = now.door; s.i = now.i + 1; s.j = now.j; if(s.i == 0 && s.j == 0) { printf("%d\n",s.door); return; } if(s.i >= 0 && s.j >= 0 && s.i <= 202 && s.j <= 202) lcm.push(s); } } if(now.j >= 1 && map[now.i][now.j - 1][0] != 1)//down { if(!flag[now.i][now.j - 1][0]) { flag[now.i][now.j - 1][0] = 1; if(map[now.i][now.j - 1][0] == 2) s.door = now.door + 1; else s.door = now.door; s.i = now.i; s.j = now.j - 1; if(s.i == 0 && s.j == 0) { printf("%d\n",s.door); return; } if(s.i >= 0 && s.j >= 0 && s.i <= 202 && s.j <= 202) lcm.push(s); } } } printf("-1\n"); return; } int main() { int x,y,d,t,i; while(~scanf("%d%d",&m,&n)) { if(m == -1 && n == -1) break; memset(map,0,sizeof(map)); while(m --) { scanf("%d%d%d%d",&x,&y,&d,&t); if(d) { for(i = y + 1;i <= y + t;i ++) { map[x][i][1] = 1; } } else { for(i = x;i < x + t;i ++) { map[i][y][0] = 1; } } } while(n --) { scanf("%d%d%d",&x,&y,&d); if(d) map[x][y + 1][1] = 2; else map[x][y][0] = 2; } double f1,f2; cin>>f1>>f2; //scanf("%lf%lf",&f1,&f2); if(f1 < 0 || f2 < 0 || f1 > 199 || f2 > 199) { printf("0\n"); } else if(m == 0 && n == 0) { printf("0\n"); } else { si = floor(f1); sj = ceil(f2); memset(flag,0,sizeof(flag)); bfs(); } } return 0; } //1516K 79MS /* 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 6 1 2 1 5 0 2 0 0 3 0 0 4 0 0 5 0 0 6 0 0 7 0 0.5 5.5 4 0 1 1 0 1 1 1 1 1 1 2 0 1 2 1 1 1 1.5 1.4 3 1 1 1 0 1 1 1 1 1 1 2 0 1 2 1 1 1.5 1.4 8 8 1 1 1 3 2 1 1 2 3 1 1 3 4 1 1 3 1 1 0 3 2 2 0 2 2 3 0 2 1 4 0 3 2 1 1 2 2 1 3 1 1 3 2 1 3 3 1 1 1 0 3 3 0 4 3 1 2.5 3.5 -1 -1 */还是忍不住要吐槽一下这题,RE了大半天了,说了墙的范围是1-199,实际上会给这个范围之外的数据!!这不是坑么!!!!!!!!!!!!!!