题目大意:二维坐标平面内给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,实际上会给这个范围之外的数据!!这不是坑么!!!!!!!!!!!!!!