hdu 4444 Walk (离散化+建图+bfs+三维判重 好题)
Walk
What’s the minimum number of turns Biaoge need to make?
As the figure above shows, there are 4 buildings and Biaoge need to make at least 3 turns to reach the amusement park(Before walking he can chose a direction freely). It is guaranteed that all the buildings are parallel to the coordination axis. Buildings may contact but overlapping is impossible. The amusement park and Biaoge’s initial positions will not contact or inside any building.
Each test case contains several lines.
The first line contains 4 integers x1, y1, x2, y2 indicating the coordinate of Biaoge and amusement park.
The second line contains one integer N(0≤N≤50), indicating the number of buildings.
Then N lines follows, each contains 4 integer x1, y1, x2, y2, indicating the coordinates of two opposite vertices of the building.
Input ends with 0 0 0 0, you should not process it.
All numbers in the input range from -10
8 to 10
8.
1
0 5 5 8
0 0 0 10
2
0 5 5 8
-2 1 0 5
0 0 0 0
2
In the first case, Biaoge can walk along the side of building, and no turn needed.
In the second case, two buildings block the direct way and Biaoge need to make 2 turns at least.
早上开始研究一个人的代码(很简洁,风格很好),研究了一个早上,思想都懂了,然后下午开始自己写,写出来后测别人贴的数据,发现最后一组数据怎么也过不了,又仔细研究了一会,发现这种思路就是错的。
我 X_X ,当时就有砸电脑的冲动了,白白浪费我我这么长时间。
ps:这题区域赛时数据水了,所以有些代码页就水过了,所以提供的解题报告有些就是错的。然后下午又重新开始搞,看了一个人的思路觉得很正确,然后晚上就开始按照这种思路写,写出来了也是各种debug,各种改代码,最后终于AC了,那叫一个爽呀!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 350
using namespace std; int n,m,ans;
int sx,sy,ex,ey;
int x[maxn],y[maxn];
int xx[maxn],yy[maxn];
int mp[maxn][maxn];
int up[maxn][maxn],down[maxn][maxn];
int le[maxn][maxn],ri[maxn][maxn];
int dx[]= {-3,3,0,0};
int dy[]= {0,0,-3,3};
bool vis[maxn][maxn][4]; // 三维判重 x+y+方向
struct Node
{
int l,d,r,u;
} rect[maxn];
struct node
{
int mx,my;
int d,cnt; // 方向 转向次数
} cur,now,q[maxn*maxn]; void showxxyy() // 输出离散化后的x y
{
int i,j;
printf("xx:\n");
for(i=1; i<=m; i++)
{
printf("%d ",xx[i]);
}
printf("\n");
printf("yy:\n");
for(i=1; i<=m; i++)
{
printf("%d ",yy[i]);
}
printf("\n");
}
void showmap() // 输出地图
{
int i,j;
printf("showmap:\n");
printf(" 1 2 3 4 5 6 7 8 9 10 11 12 \n");
for(i=1; i<=3*xx[m]; i++)
{
printf("%3d: ",i);
for(j=1; j<=3*yy[m]; j++)
{
printf("%d",mp[i][j]);
}
printf("\n");
}
}
void disc() // 离散化
{
int i,j;
m=2*n+2;
sort(x+1,x+m+1);
xx[1]=1;
for(i=2; i<=m; i++)
{
if(x[i]==x[i-1]) xx[i]=xx[i-1];
else xx[i]=xx[i-1]+1;
}
sort(y+1,y+m+1);
yy[1]=1;
for(i=2; i<=m; i++)
{
if(y[i]==y[i-1]) yy[i]=yy[i-1];
else yy[i]=yy[i-1]+1;
}
// showxxyy();
}
int find(int v,int k) // 找到离散化对应的点
{
int i,j;
if(k)
{
for(i=1; i<=m; i++)
{
if(y[i]==v) return yy[i];
}
}
else
{
for(i=1; i<=m; i++)
{
if(x[i]==v) return xx[i];
}
}
}
void buildgraph() // 将1*1的方格转化为3*3的方格后建图
{
int i,j,ni,nj,k,l,d,r,u;
memset(mp,0,sizeof(mp));
memset(up,1,sizeof(up));
memset(down,1,sizeof(down));
memset(le,1,sizeof(le));
memset(ri,1,sizeof(ri));
for(k=1; k<=n; k++) // 将矩形在地图上涂黑
{
l=3*find(rect[k].l,0)+1;
d=3*find(rect[k].d,1)+1;
r=3*find(rect[k].r,0)-1;
u=3*find(rect[k].u,1)-1;
// printf("l:%d d:%d r:%d u:%d\n",l,d,r,u);
for(i=l; i<=r; i++)
{
for(j=d; j<=u; j++)
{
mp[i][j]=1;
}
}
}
for(i=1; i<=xx[m]; i++) // 记录是否能走 是否是‘L’型区域
{
for(j=1; j<=yy[m]; j++)
{
ni=3*i;
nj=3*j;
if(mp[ni-1][nj-1]&&mp[ni+1][nj+1])
{
up[ni][nj]=down[ni][nj]=le[ni][nj]=ri[ni][nj]=-1;
}
else if(mp[ni+1][nj-1]&&mp[ni-1][nj+1]) up[ni][nj]=down[ni][nj]=le[ni][nj]=ri[ni][nj]=-2;
if(mp[ni-1][nj-1]&&mp[ni-1][nj+1]) up[ni][nj]=0;
if(mp[ni+1][nj-1]&&mp[ni+1][nj+1]) down[ni][nj]=0;
if(mp[ni-1][nj-1]&&mp[ni+1][nj-1]) le[ni][nj]=0;
if(mp[ni-1][nj+1]&&mp[ni+1][nj+1]) ri[ni][nj]=0;
}
}
// showmap();
}
bool bfs() // 图建好了 就是简单的bfs了
{
int i,j,nx,ny,nd,ncnt,tx,ty;
int head=0,tail=-1;
memset(vis,0,sizeof(vis));
sx=3*find(sx,0);
sy=3*find(sy,1);
ex=3*find(ex,0);
ey=3*find(ey,1);
// printf("sx:%d sy:%d ex:%d ey:%d\n",sx/3,sy/3,ex/3,ey/3);
cur.mx=sx;
cur.my=sy;
cur.d=-1;
cur.cnt=0;
vis[sx][sy][0]=vis[sx][sy][1]=vis[sx][sy][2]=vis[sx][sy][3]=1;
q[++tail]=cur;
while(head<=tail)
{
now=q[head];
head++;
nx=now.mx;
ny=now.my;
nd=now.d;
ncnt=now.cnt;
// printf("nx:%d ny:%d nd:%d ncnt:%d\n",nx/3,ny/3,nd,ncnt);
if(nx==ex&&ny==ey)
{
ans=ncnt;
return true ;
}
for(i=0; i<4; i++)
{
if(i==0&&!up[nx][ny]||i==1&&!down[nx][ny]||i==2&&!le[nx][ny]||i==3&&!ri[nx][ny]) continue ; // 判断是否能往这个方向走
if(up[nx][ny]==-1) // 对‘L’型区域特判
{
if(i==0&&(nd==0||nd==3)) continue ;
else if(i==1&&(nd==1||nd==2)) continue ;
else if(i==2&&(nd==2||nd==1)) continue ;
else if(i==3&&(nd==3||nd==0)) continue ;
}
else if(up[nx][ny]==-2)
{
if(i==0&&(nd==0||nd==2)) continue ;
else if(i==1&&(nd==1||nd==3)) continue ;
else if(i==2&&(nd==2||nd==0)) continue ;
else if(i==3&&(nd==3||nd==1)) continue ;
}
tx=nx+dx[i];
ty=ny+dy[i];
while(tx>=1&&tx<=3*xx[m]&&ty>=1&&ty<=3*yy[m]&&!mp[tx][ty]) // 每次向一个方向搜索
{
if(!vis[tx][ty][i])
{
vis[tx][ty][i]=1;
cur.mx=tx;
cur.my=ty;
cur.d=i;
cur.cnt=ncnt;
if(cur.d!=nd&&nd!=-1) cur.cnt++;
q[++tail]=cur;
}
if(i==0&&!up[tx][ty]||i==1&&!down[tx][ty]||i==2&&!le[tx][ty]||i==3&&!ri[tx][ty]) break ;
if(up[tx][ty]==-1||up[tx][ty]==-2) break ;
tx+=dx[i];
ty+=dy[i];
}
}
}
return false ;
}
int main()
{
int i,j;
int x1,y1,x2,y2,l,d,r,u;
while(scanf("%d%d%d%d",&sx,&sy,&ex,&ey),sx||sy||ex||ey)
{
scanf("%d",&n);
for(i=1; i<=n; i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
l=min(x1,x2);
r=max(x1,x2);
d=min(y1,y2);
u=max(y1,y2);
x[i]=rect[i].l=l;
x[i+n]=rect[i].r=r;
y[i]=rect[i].d=d;
y[i+n]=rect[i].u=u;
}
x[2*n+1]=sx;
x[2*n+2]=ex;
y[2*n+1]=sy;
y[2*n+2]=ey;
disc();
buildgraph();
if(bfs()) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
/* // 绕路 2
1 1 1 4
1
0 2 2 3 // 直走 0
1 1 1 4
1
3 3 4 5 // 沿着边直走 0
0 1 0 7
2
0 2 2 3
-1 4 0 5 // 沿着边直走 0
0 1 0 7
2
0 2 2 3
0 3 2 4 // 无法穿过缝隙,绕路 2
0 1 0 7
2
0 2 2 3
-1 3 0 5 // 无法到达 -1
0 0 5 5
4
-1 1 1 2
1 -1 2 1
-1 -1 1 -2
-1 1 -2 -1 // 同点经过两次。 5
1 3 4 1
10
-1 -1 3 2
3 -1 7 0
7 -1 11 3
9 3 11 7
-1 7 11 9
0 5 4 7
-1 2 0 7
2 2 4 3
4 3 5 4
5 4 8 6
*/
hdu 4444 Walk (离散化+建图+bfs+三维判重 好题)的更多相关文章
- HDU 4444 Walk (离散化建图+BFS+记忆化搜索) 绝对经典
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4444 题意:给你一些n个矩形,给你一个起点,一个终点,要你求从起点到终点最少需要转多少个弯 题解:因为 ...
- BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS
BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N ...
- HDU 4292 Food (建图思维 + 最大流)
(点击此处查看原题) 题目分析 题意:某个餐馆出售f种食物,d种饮料,其中,第i种食物有fi份,第i种饮料有di份:此时有n个人来餐馆吃饭,这n个人必须有一份食物和一份饮料才会留下来吃饭,否则,他将离 ...
- Eliminate the Conflict HDU - 4115(2-sat 建图 hhh)
题意: 石头剪刀布 分别为1.2.3,有n轮,给出了小A这n轮出什么,然后m行,每行三个数a b k,如果k为0 表示小B必须在第a轮和第b轮的策略一样,如果k为1 表示小B在第a轮和第b轮的策略不一 ...
- Meeting HDU - 5521 虚点建图
Problem Description Bessie and her friend Elsie decide to have a meeting. However, after Farmer John ...
- 逃生 HDU 4857(反向建图 + 拓扑排序)
逃生 链接 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必 ...
- hdu 1226 bfs+余数判重+大数取余
题目: 超级密码 Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- poj 1465 Multiple(bfs+余数判重)
题意:给出m个数字,要求组合成能够被n整除的最小十进制数. 分析:用到了余数判重,在这里我详细的解释了.其它就没有什么了. #include<cstdio> #include<cma ...
- Keyboarding (bfs+预处理+判重优化)
# #10030. 「一本通 1.4 练习 2」Keyboarding [题目描述] 给定一个 $r$ 行 $c$ 列的在电视上的"虚拟键盘",通过「上,下,左,右,选择」共 $5 ...
随机推荐
- 模式识别 - 处理多个演示样本研究(MIL)特点(matlab)
处理多个演示样本研究(MIL)特点(matlab) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/27206325 多演示样例学习 ...
- NET平台机器学习组件-Infer.NET
NET平台机器学习组件-Infer.NET(三) Learner API—数据映射与序列化 阅读目录 关于本文档的说明 1.基本介绍 2.标准数据格式的映射 3.本地数据格式映射 4.评估数据格式映射 ...
- ThinkPHP页面跳转、Ajax技巧详细介绍(十八)
原文:ThinkPHP页面跳转.Ajax技巧详细介绍(十八) ThinkPHP页面跳转.Ajax技巧详细介绍 一.页面跳转 $this->success('查询成功',U('User/test' ...
- [Android学习笔记]jackson库的使用
Jackson库一般用于序列化和反序列化操作,通常会涉及到的操作是: 1. Java Object -> Json String 2. Java Object -> Xml String ...
- 14.4.3.1 The InnoDB Buffer Pool
14.4.3.1 The InnoDB Buffer Pool 14.4.3.2 Configuring Multiple Buffer Pool Instances 14.4.3.3 Making ...
- android doGet和doPost
doGet和doPost的差别 get和post是http协议的两种方法,另外还有head, delete等 这两种方法有本质的差别,get仅仅有一个流,參数附加在url后.大小个数有严格限制且仅仅 ...
- 微信 SDK 不能 分享
说多了都是泪水,真的. 前段时间,做好了微信的分享功能,测试通过的,最近我又跑了一遍用例,发现不能启动微信客户端了,怎么都启动不了,日志如下:ignore wechat app signature v ...
- 2014/08/23——OJ出现waiting...
问题: 今天中午,裴主解决OJ他缓慢的问题后,开着.我跟着oj他递给发现了一个话题waiting该..... 和全哥.均觉得測评程序挂了.于是重新启动測系统,还waiting.....(測评系统的进程 ...
- python列表和QVariant
pyqt中.要给QAbstractTableModel的setData函数传递一个list參数: [20,'00:00:19'] 涉及到QVariant和list的转换. 能够使用QVariant类中 ...
- Creating Contextual Menus创建上下文菜单
A contextual menu offers actions that affect a specific item or context frame in the UI. You can pro ...