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. ThreadPoolExecutor原理和使用

    大家先从ThreadPoolExecutor的整体流程入手: 针对ThreadPoolExecutor代码.我们来看下execute方法: public void execute(Runnable c ...

  2. C#调用JS

    cmd调用phantomjs 官方资料:http://phantomjs.org/quick-start.html 手动执行 从官方下载phantomjs.exe,拷贝它与要执行的js同目录打开cmd ...

  3. ASP.NET Core 配置身份验证

    以AspUser的Password为例,去掉最少1个大写字母,1个小写字母等等坑爹的要求在Startup的ConfigureServices中进行配置 services.Configure<Id ...

  4. WPF 简单打印

    <Window x:Class="_096基本打印.MainWindow"        xmlns="http://schemas.microsoft.com/w ...

  5. 一步一步造个IoC轮子(一):IoC是什么

    一步一步造个Ioc轮子目录 一步一步造个IoC轮子(一):IoC是什么 一步一步造个IoC轮子(二):详解泛型工厂 一步一步造个IoC轮子(三):构造基本的IoC容器 前言 .net core正式版前 ...

  6. css3的calc() css3的百分比减宽,减高,加,乘,除,适合用于后台的排版定位

    css3的calc() css3的百分比减宽,减高,加,乘,除,适合用于后台的排版定位 浏览器支持IE9+.FF4.0+.Chrome19+.Safari6+ calc()语法非常简单,就像我们小时候 ...

  7. 【Linux】samba服务

    samba是一个实现不同操作系统之间文件共享和打印机共享的一种SMB协议的免费软件. ①Samba软件包的安装 使用源安装,在终端中输入如下命令: #sudo apt-get install samb ...

  8. codewars杂记: 寻找缺失的数

    题目描述: 给出一个整数列表,找出该列表无法通过各种组合求和得到的最小的整数. 示例: solve([1,2,8,7]) = 4, because we can get 1, 2, 1+2=3. Bu ...

  9. Win10《芒果TV》商店内测版更新至v3.1.6:率先支持Xbox One平台 - 参与反馈,赢取VIP奖励

    芒果TV For Win10商店内测版 v3.1.6 于2016年9月1日星期四下午正式登陆商店 主要是优化手机版视频下载相关设置.策略.风险提示,并升级兼容目标,率先支持Xbox One平台,覆盖更 ...

  10. foreach获取索引值

    List<" }; foreach (string item in items) { int index = items.IndexOf(item); Console.WriteLin ...