http://acm.hdu.edu.cn/showproblem.php?pid=4444

题意:给出一个起点一个终点,给出n个矩形的两个对立顶点,问最少需要拐多少次弯可以从起点到达终点,如果不能输出-1.

思路:http://blog.csdn.net/asdfgh0308/article/details/8125832看的是这里的。

因为边界是可以走的,所以不能用点直接来做。

这里用到的就是把一个点拆成一个3*3的方块,中心点就是本身,然后对图进行染色。举个染色的例子:

如果染的是某个颜色的顶点,那么对于那个顶点应当将3*3的方块那样染。

接下来就考虑一种‘L’型拐角的怎么去拐,很多种情况需要去列举。

还有一种就是点的两侧都是被染过的,说明这是一个有两条边界相交的点,因此也是不能走的。

还有注意循环结束的条件不是(SX +SY + EX + EY),因为点可以是负,因这个WA了一个晚上才发现!!!

 #include <bits/stdc++.h>
using namespace std;
#define N 1010
#define INF 0x3f3f3f3f
struct node {
int x, y;
} p[N][];
struct P {
int x, y, dir;
P () {}
P (int _x, int _y, int _dir) : x(_x), y(_y), dir(_dir) {};
};
int xx[N], yy[N], x[N], y[N], cx, cy, n, sx, sy, ex, ey;
int mp[N][N], dis[N][N][], dx[] = {, -, , }, dy[] = {, , , -}; // 上下右左
bool vis[N][N][];
void Addpoint(int &x, int &y) {
x *= , y *= ;
cx++; xx[cx] = x;
cx++; xx[cx] = x + ;
cx++; xx[cx] = x - ;
cy++; yy[cy] = y;
cy++; yy[cy] = y + ;
cy++; yy[cy] = y - ;
}
void Find(int &wx, int &wy) {
wx = lower_bound(xx + , xx + + cx, wx) - xx;
wy = lower_bound(yy + , yy + + cy, wy) - yy;
}
void Turn(int x, int y) {
if(mp[x-][y-] && mp[x+][y+] && mp[x+][y-] && mp[x-][y+]) mp[x][y] = -; // 四个角都不行
else if(mp[x+][y+] && mp[x+][y-] && mp[x-][y+]) mp[x][y] = ; // 左下角可以
else if(mp[x+][y-] && mp[x+][y+] && mp[x-][y-]) mp[x][y] = ; // 右下角可以
else if(mp[x-][y-] && mp[x-][y+] && mp[x+][y-]) mp[x][y] = ; // 右上角可以
else if(mp[x-][y-] && mp[x-][y+] && mp[x+][y+]) mp[x][y] = ; // 左上角可以
else if(mp[x+][y-] && mp[x-][y+]) mp[x][y] = ; // 左下角右上角可以
else if(mp[x-][y-] && mp[x+][y+]) mp[x][y] = ; // 左上角右下角可以
if(mp[x-][y] && mp[x+][y]) mp[x][y] = -;
if(mp[x][y-] && mp[x][y+]) mp[x][y] = -;
}
void Build() {
memset(mp, , sizeof(mp));
for(int i = ; i <= n; i++)
for(int j = p[i][].x + ; j <= p[i][].x - ; j++)
for(int k = p[i][].y + ; k <= p[i][].y - ; k++)
mp[j][k] = -;
for(int i = ; i <= cx; i++)
for(int j = ; j <= cy; j++)
if(!mp[i][j]) Turn(i, j);
}
bool Check(int x, int y, int nx, int ny, int pdir, int dir) {
if(nx < || nx > cx || ny < || ny > cy) return false;
if(!mp[x][y]) return true;
if(dir == ) { // 上
if(pdir == && (mp[x][y] == || mp[x][y] == )) return true;
if(pdir == && (mp[x][y] == || mp[x][y] == )) return true;
} else if(dir == ) { // 下
if(pdir == && (mp[x][y] == || mp[x][y] == )) return true;
if(pdir == && (mp[x][y] == || mp[x][y] == )) return true;
} else if(dir == ) {
if(pdir == && (mp[x][y] == || mp[x][y] == )) return true;
if(pdir == && (mp[x][y] == || mp[x][y] == )) return true;
} else {
if(pdir == && (mp[x][y] == || mp[x][y] == )) return true;
if(pdir == && (mp[x][y] == || mp[x][y] == )) return true;
}
return false;
} int BFS() {
memset(vis, , sizeof(vis));
memset(dis, INF, sizeof(dis));
queue<P> que; while(!que.empty()) que.pop();
for(int i = ; i < ; i++) {
que.push(P(sx, sy, i)), dis[sx][sy][i] = , vis[sx][sy][i] = ;
}
int ans = INF;
while(!que.empty()) {
P now = que.front(); que.pop();
int x = now.x, y = now.y, dir = now.dir;
if(x == ex && y == ey) ans = min(ans, dis[x][y][dir]);
vis[x][y][dir] = ;
for(int k = ; k < ; k++) {
int nx = now.x + dx[k], ny = now.y + dy[k], ndir = k;
if(!Check(x, y, nx, ny, dir, ndir)) continue;
int w = ndir == dir ? : ; w += dis[x][y][dir];
if(w < dis[nx][ny][ndir]) {
dis[nx][ny][ndir] = w;
if(!vis[nx][ny][ndir]) vis[nx][ny][ndir] = , que.push(P(nx, ny, ndir));
}
}
}
if(ans == INF) puts("-1");
else printf("%d\n", ans);
// puts("");
}
int main() {
while(scanf("%d%d%d%d", &sx, &sy, &ex, &ey)) { // sx + sy + ex + ey == 0
if(!sx && !sy && !ex && !ey) break;
scanf("%d", &n); cx = cy = ;
for(int i = ; i <= n; i++) {
int x1, x2, y1, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
Addpoint(x1, y1); Addpoint(x2, y2);
if(x1 > x2) swap(x1, x2);
if(y1 > y2) swap(y1, y2);
p[i][] = (node) { x1, y1 };
p[i][] = (node) { x2, y1 };
p[i][] = (node) { x2, y2 };
p[i][] = (node) { x1, y2 };
}
Addpoint(sx, sy); Addpoint(ex, ey);
int tx = cx, ty = cy;
sort(xx + , xx + + cx); cx = unique(xx + , xx + + cx) - xx - ;
sort(yy + , yy + + cy); cy = unique(yy + , yy + + cy) - yy - ;
for(int i = ; i <= n; i++)
for(int j = ; j < ; j++)
Find(p[i][j].x, p[i][j].y);
Find(sx, sy); Find(ex, ey);
Build();
BFS();
}
return ;
}

HDU 4444:Walk(思维建图+BFS)***的更多相关文章

  1. HDU 4444 Walk (离散化建图+BFS+记忆化搜索) 绝对经典

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4444 题意:给你一些n个矩形,给你一个起点,一个终点,要你求从起点到终点最少需要转多少个弯 题解:因为 ...

  2. BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS

    BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N ...

  3. hdu 4444 Walk (离散化+建图+bfs+三维判重 好题)

    Walk Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submi ...

  4. HDU 4370 0 or 1(spfa+思维建图+计算最小环)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4370 题目大意:有一个n*n的矩阵Cij(1<=i,j<=n),要找到矩阵Xij(i< ...

  5. HDU 4292 Food (建图思维 + 最大流)

    (点击此处查看原题) 题目分析 题意:某个餐馆出售f种食物,d种饮料,其中,第i种食物有fi份,第i种饮料有di份:此时有n个人来餐馆吃饭,这n个人必须有一份食物和一份饮料才会留下来吃饭,否则,他将离 ...

  6. 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轮的策略不一 ...

  7. Codeforces Round #523 (Div. 2) E. Politics(最小费+思维建图)

    https://codeforces.com/contest/1061/problem/E 题意 有n个点(<=500),标记第i个点的代价a[i],然后分别在这n个点建两棵树,对于每颗树的每个 ...

  8. Meeting HDU - 5521 虚点建图

    Problem Description Bessie and her friend Elsie decide to have a meeting. However, after Farmer John ...

  9. 逃生 HDU 4857(反向建图 + 拓扑排序)

    逃生 链接 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必 ...

随机推荐

  1. Why aren't more desktop apps written with Qt?(quora.com系列文章)

    As far as I know and have understood in my experience with Qt, it's a very good and easy to learn li ...

  2. XF 按钮控件

    <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http:/ ...

  3. WPF 通过CommandBinding捕获命令

    RoutedCommand与业务逻辑无关,业务逻辑是通过CommandBinding来实现 using System; using System.Collections.Generic;using S ...

  4. php 获取今日、昨日、本周,上周、本月,上月,季度的起始时间戳和结束时间戳的方法

    php 获取今日.昨日.上周.本月的起始时间戳和结束时间戳的方法,主要使用到了 php 的时间函数 mktime.下面首先还是直奔主题以示例说明如何使用 mktime 获取今日.昨日.上周.本月的起始 ...

  5. 加载dll、lib库(例子的代码很全)

    是关于如何加载dll或lib库的.可以看这篇bog   Qt调用dll中的功能函数点击打开链接 **************************************************** ...

  6. 没有安装提供程序“System.Data.SqlServerCe.3.5”的解决方法

    在Windows 8.1系统下运行带数据库功能的应用,报错并提示:“System.InvalidOperationException”类型的未经处理的异常在 System.Data.Linq.dll ...

  7. Android零基础入门第54节:视图切换组件ViewSwitcher

    原文:Android零基础入门第54节:视图切换组件ViewSwitcher 前面三期学习了ProgressBar系列组件,那本期开始一起来学习ViewAnimator组件. 一.ViewAnimat ...

  8. 如何作为一个优秀的ERP实施顾问

    原文地址:如何作为一个优秀的ERP实施顾问作者:天思软件 作一个优秀的ERP实施顾问无论是天思.金蝶,用友,还是其他业务软件.实施顾问的发展道路都差不多. 1.初级实施顾问,中级实施顾问,高级实施顾问 ...

  9. 转换GMT秒数为日期时间格式-Delphi源码

    转换GMT秒数为日期时间格式-Delphi源码.收藏最近在写PE分析工具的时候,需要转换TimeDateStamp字段值为日期时间格式,这是Delphi的源码. //把GMT时间的秒数转换成日期时间格 ...

  10. 高效的DDoS攻击探测与分析工具 – FastNetMon

    快速使用Romanysoft LAB的技术实现 HTML 开发Mac OS App,并销售到苹果应用商店中.   <HTML开发Mac OS App 视频教程> 土豆网同步更新:http: ...