hdu4444Walk(离散化+建图+记忆化搜索)
来源:互联网 发布:作图软件大全 编辑:程序博客网 时间:2024/06/09 19:42
Walk
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1130 Accepted Submission(s): 185
Problem Description
Biaoge is planning to walk to amusement park. The city he lives can be abstracted as a 2D plane. Biaoge is at (x1, y1) and the amusement park is at (x2, y2). There are also some rectangle buildings. Biaoge can only walk parallel to the coordinate axis. Of course Biaoge can’t walk across the buildings.
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.
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.
Input
There are multiple test case.
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 -108 to 108.
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 -108 to 108.
Output
For each test case, output the number of least turns in a single line. If Biaoge can’t reach the amusement park, output -1 instead.
Sample Input
0 0 0 1010 5 5 80 0 0 1020 5 5 8-2 1 0 50 0 0 0
Sample Output
02HintIn 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.
题目大意:二维平面内给n个矩形,再给2个点,求两点之间所有路径中最少的拐弯次数。
题目分析:好题!乍一看这题跟这道hdu1728一样的。只不过此题要自己把图建出来。矩形很少,坐标很广,所以首先离散化,然后建图。比赛的时候就栽在了建图上。由于此题可以沿着建筑物边缘走(walk along),所以就不能单纯的按格子建图了。如果建筑物的墙有公共部分,即使只有一个点,也是不能通过的,如果建筑物的墙在一条直线上,如果没有公共部分,那么是可以沿着墙直走的。所以考虑将一个格子拆成3*3的格子,如果两面墙有公共部分,那么将中间一行也填墙,如果没有公共部分,则可以走。
这题的精华在建图,图一建就很简单了,随便水过就可以了。我用的记忆化搜索,效率不是很高。
详情请见代码:
#include <iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cctype>#include<cmath>#include<algorithm>#include<queue>#include<map>#include<vector>#include<set>#include<string>using namespace std;const int N = 430;const int M = 10000005;const int INF = 0x3f3f3f3f;const double eps = 1e-6;const double PI = acos(-1.0);int g[N][N];int step[N][N];int dx[] = {1,-1,0,0};int dy[] = {0,0,1,-1};int si,sj,ei,ej;struct node{ int x1,y1,x2,y2;}rect[N];struct nd{ int x,y,turn;}ss,now,xh[M];int hx[N],hy[N];int nx,ny;int n;int getx(int x){ int l,r,mid; l = 1;r = nx; while(l <= r) { mid = (l + r)>>1; if(hx[mid] == x) return mid; else if(hx[mid] > x) r = mid - 1; else l = mid + 1; }}int gety(int x){ int l,r,mid; l = 1;r = ny; while(l <= r) { mid = (l + r)>>1; if(hy[mid] == x) return mid; else if(hy[mid] > x) r = mid - 1; else l = mid + 1; }}void add(int l1,int r1,int l2,int r2){ int i,j; for(i = l2;i <= r2;i ++) { g[l1][i] = g[r1][i] = 1; if(g[l1 - 2][i] == 1) g[l1 - 1][i] = 1; if(g[r1 - 2][i] == 1) g[r1 + 1][i] = 1; } for(i = l1 + 1;i < r1;i ++) { g[i][l2] = g[i][r2] = 1; if(g[i][l2 - 2] == 1) g[i][l2 - 1] = 1; if(g[i][r2 + 2] == 1) g[i][r2 + 1] = 1; } if(g[r1 + 2][r2 + 2] == 1) g[r1 + 1][r2 + 1] = 1; if(g[l1 - 2][l2 - 2] == 1) g[l1 - 1][l2 - 1] = 1; if(g[l1 - 2][r2 + 2] == 1) g[l1 - 1][r2 + 1] = 1; if(g[r1 + 2][l2 - 2] == 1) g[r1 + 1][l2 - 1] = 1;}void makeg(){ int i,j; memset(g,0,sizeof(g)); int l1,r1,l2,r2; si = getx(rect[0].x1); sj = gety(rect[0].y1); ei = getx(rect[0].x2); ej = gety(rect[0].y2); for(i = ei * 3;i >= ei * 3 - 2;i --) { for(j = ej * 3;j >= ej * 3 - 2;j --) g[i][j] = 5; } for(i = 1;i <= n;i ++) { l1 = getx(rect[i].x1); r1 = getx(rect[i].x2); l2 = gety(rect[i].y1); r2 = gety(rect[i].y2); add(l1*3,r1*3-2,l2*3,r2*3-2); }}bool isok(int x,int y){ return (x >= 0 && y >= 0 && x <= nx + nx + nx + 1 && y <= ny + ny + ny + 1);}void bfs(){ int head,tail; int i,j; head = tail = 0;//起点不止一个 ss.turn = -1; for(i = si * 3;i >= si * 3 - 2;i --) { for(j = sj * 3;j >= sj * 3 - 2;j --) if(g[i][j] != 1) { ss.x = i; ss.y = j; xh[tail ++] = ss; } } while(head != tail) { now = xh[head ++]; if(head >= M) head -= M; for(i = 0;i < 4;i ++) { ss = now; ss.turn ++; int tx = ss.x + dx[i]; int ty = ss.y + dy[i]; while(isok(tx,ty) && g[tx][ty] != 1) { if(step[tx][ty] > ss.turn) { step[tx][ty] = ss.turn; ss.x = tx; ss.y = ty; if(g[tx][ty] == 5)//直接返回比较快 { printf("%d\n",step[tx][ty]); return; } xh[tail ++] = ss; if(tail >= M) tail -= M; } tx += dx[i]; ty += dy[i]; } } } printf("-1\n");}void solve(){ int i,j; for(i = 0;i <= 3*nx + 1;i ++)//show graph { for(j = 0;j <= 3*ny + 1;j ++) step[i][j] = INF; } bfs();}int main(){ int i,j; while(scanf("%d%d%d%d",&hx[1],&hy[1],&hx[2],&hy[2])) { rect[0].x1 = hx[1]; rect[0].y1 = hy[1]; rect[0].x2 = hx[2]; rect[0].y2 = hy[2]; if(!hx[1] && !hy[1] && !hx[2] && !hy[2]) break; scanf("%d",&n); j = 3; for(i = 1;i <= n;i ++) { scanf("%d%d%d%d",&rect[i].x1,&rect[i].y1,&rect[i].x2,&rect[i].y2); hx[j] = rect[i].x1; hy[j ++] = rect[i].y1; hx[j] = rect[i].x2; hy[j ++] = rect[i].y2; } sort(hx + 1,hx + j); sort(hy + 1,hy + j); nx = 2; for(i = 2;i < j;i ++) if(hx[i] != hx[i - 1]) hx[nx ++] = hx[i]; nx --; ny = 2; for(i = 2;i < j;i ++) if(hy[i] != hy[i - 1]) hy[ny ++] = hy[i]; ny --; makeg(); solve(); } return 0;}//93MS 2140K/*0 0 3 342 0 4 20 2 2 44 2 6 42 4 4 60 0 0 1010 5 5 80 0 0 1020 5 5 8-2 1 0 5100 -50 10 204-100 15 -20 30-5 25 50 100-30 -30 70 -2070 -20 120 805 -1 60 731 8 101 8880 0 49 550 0 100 60 -1 2 13-1 0 0 10 1 1 21 -2 3 00 0 0 101-3 5 0 80 -1 -1 09-3 4 4 54 -3 5 5-2 -3 4 -2-3 -3 -2 4-1 2 0 41 1 3 30 0 1 1-2 -2 0 02 -2 3 00 0 0 1020 5 5 80 2 4 50 0 0 1020 5 5 8-2 1 0 40 0 0 1020 0 5 8-2 1 0 50 0 1 100*//*ans:-10232105002*/
- hdu4444Walk(离散化+建图+记忆化搜索)
- uva1637(记忆化搜索,离散概率)
- soj 2505: The County Fair(离散化 + 记忆化搜索)
- 搜索+离散化思想
- HDU 4444 Walk (离散化建图+BFS+记忆化搜索) 绝对经典
- USACO5.5 降维扫描/离散_最小表示法_记忆化搜索
- 记忆化搜索例题
- PKU1088---记忆化搜索
- PKU1088 记忆化搜索
- HDU1078 记忆化搜索
- HDU1501 记忆化搜索
- HDU1978 记忆化搜索
- poj1661 记忆化搜索
- zoj1107记忆化搜索
- poj1191(记忆化搜索)
- 滑雪 记忆化搜索
- hdu3779---记忆化搜索
- hdu2452---记忆化搜索
- On Error GOTO的好处
- Asp.net 使用My97DatePicker进行日期选择
- Vacanti:我是如何学习编程的
- epoll
- 请好好做人,快乐和幸福
- hdu4444Walk(离散化+建图+记忆化搜索)
- 无线不能支持某些移动设备的原因
- Redis使用总结之与Memcached异同
- phpstorm的快捷键
- 常用正则表达式例子
- Grails2中的Many-to-many关系
- Cain嗅探到的RDP包批量解析为用户名+密码的php脚本
- Stratos2.0的架构
- POJ 1423 Greatest Common Increasing Subsequence【裸LCIS】