题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4444

题意:给你一些n个矩形,给你一个起点,一个终点,要你求从起点到终点最少需要转多少个弯

题解:因为矩形数量很少50个,可以离散化成102*102的坐标,但是人可以贴着墙壁走,但不能穿过墙壁

所以每个点要分成9等分。建筑物的边占1/3,但是这样有漏洞。

1、当两个墙壁贴在一起,中间还可以过,所以要填补中间

2、当两个矩形的角重合,中间也可以过,要填补中间,但是只能填补中间一个点,不能填补全部的9个点。

还有一点要注意的是,起点有多个,终点也有多个,从任意一起点到任意一终点即可,因为有一些特殊数据,我的例子里面有

图建好了,直接BFS记忆化搜索即可。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <sstream>
using namespace std; typedef long long LL;
const int N=410;
const LL II=100000000;
const int INF=0x3f3f3f3f;
const int M=12345678;
const double PI=acos(-1.0); int sx,sy,ex,ey;
int si,sj,ei,ej;
int n,nx,ny;
int x[N],y[N];
int g[N][N],step[N][N];
int t[4][2]={1,0,-1,0,0,1,0,-1}; struct node
{
int x1,x2,y1,y2;
}rect[N]; struct xiaohao
{
int xx,yy;
int step;
}e,w,xh[M]; int nextint()
{
int f=1;
char c;
while((c=getchar())<'0'||c>'9')
if(c=='-')
f=-1;
int sum=c-'0';
while((c=getchar())>='0'&&c<='9')
sum=sum*10+c-'0';
return sum*f;
} void lisanhua(int m) //离散化
{
int i,j;
sort(x+1,x+m+1);
sort(y+1,y+m+1);
nx=1;
for(i=2;i<=m;i++)//去重
if(x[i]!=x[i-1])
x[++nx]=x[i];
ny=1;
for(i=2;i<=m;i++)//去重
if(y[i]!=y[i-1])
y[++ny]=y[i];
} int getx(int xx)//数据量大的时候可以用二分查找
{
for(int i=1;i<=nx;i++)
if(x[i]==xx)
return i;
} int gety(int yy)
{
for(int i=1;i<=ny;i++)
if(y[i]==yy)
return i;
} void add(int x1,int x2,int y1,int y2)
{
int i,j;
for(i=x1;i<=x2;i++)
for(j=y1;j<=y2;j++)
g[i][j]=1;//建筑物标记为1
} void jiantu()
{
int i,j,x1,x2,y1,y2;
memset(g,0,sizeof(g));
si=getx(sx);
sj=gety(sy);
ei=getx(ex);
ej=gety(ey); for(i=si*3;i>=si*3-2;i--)//起点,这个地方9个格子全部要标记为5
for(j=sj*3;j>=sj*3-2;j--)
g[i][j]=5;
for(i=ei*3;i>=ei*3-2;i--)//终点,这个地方9个格子全部要标记为6
for(j=ej*3;j>=ej*3-2;j--)
g[i][j]=6; for(i=1;i<=n;i++)
{
x1=getx(rect[i].x1);
y1=gety(rect[i].y1);
x2=getx(rect[i].x2);
y2=gety(rect[i].y2); add(x1*3,x2*3-2,y1*3,y2*3-2);
}
for(i=1;i<=nx;i++)//将重合的点中间补上
for(j=1;j<=ny;j++)
{
if(g[i*3-2][j*3-2]==1&&g[i*3][j*3]==1||g[i*3-2][j*3]==1&&g[i*3][j*3-2]==1)
g[i*3-1][j*3-1]=1;
if(g[i*3-1][j*3-2]==1&&g[i*3-1][j*3]==1)
g[i*3-1][j*3-1]=1;
if(g[i*3-2][j*3-1]==1&&g[i*3][j*3-1]==1)
g[i*3-1][j*3-1]=1;
}
// for(i=1;i<=3*nx;i++) //输出离散化后的图
// {
// for(j=1;j<=3*ny;j++)
// printf("%d",g[i][j]);
// printf("\n");
// }
} bool ok(int tx,int ty)
{
return (tx>=0&&tx<=3*nx&&ty>=0&&ty<=3*ny);
} void BFS()
{
int i,j,head=0,tail=0;
w.step=-1;
for(i=si*3;i>=si*3-2;i--)
for(j=sj*3;j>=sj*3-2;j--)
if(g[i][j]==5)
{
w.xx=i;w.yy=j;
xh[tail++]=w;
}
memset(step,INF,sizeof(step));
step[w.xx][w.yy]=-1;
while(head!=tail)
{
e=xh[head++];
if(head==M)
head=0;
for(i=0;i<4;i++)
{
w=e;
w.step++;
int tx=w.xx+t[i][0];
int ty=w.yy+t[i][1];
while(ok(tx,ty)&&g[tx][ty]!=1)//判断是否在界内,而且能走
{
if(w.step<step[tx][ty])
{
if(g[tx][ty]==6)
{
printf("%d\n",w.step);
return ;
}
step[tx][ty]=w.step;
w.xx=tx;
w.yy=ty;
xh[tail++]=w;
if(tail==M)
tail=0;
}
tx+=t[i][0];
ty+=t[i][1];
}
}
}
printf("-1\n");
} int main()
{
int i,j;
while(scanf("%d%d%d%d",&sx,&sy,&ex,&ey))
{
int x1,x2,y1,y2,m;
if((!sx)&&(!sy)&&(!ex)&&(!ey))
break;
if(sx==ex&&sy==ey)
{
printf("0\n");
continue;
}
m=0;
rect[0].x1=x[++m]=sx;
rect[0].y1=y[m]=sy;
rect[0].x2=x[++m]=ex;
rect[0].y2=y[m]=ey;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1>x2)//防止有的数据先是右上点再是左下点
swap(x1,x2),swap(y1,y2); x[++m]=rect[i].x1=x1;
y[m]=rect[i].y1=y1;
x[++m]=rect[i].x2=x2;
y[m]=rect[i].y2=y2;
} lisanhua(m);
jiantu();
BFS();
}
return 0;
} /*
0 0 3 3
4
2 0 4 2
0 2 2 4
4 2 6 4
2 4 4 6 100 -50 10 20
4
-100 15 -20 30
-5 25 50 100
-30 -30 70 -20
70 -20 120 80 5 -1 60 7
3
1 8 101 888
0 0 49 5
50 0 100 6 0 -1 2 1
3
-1 0 0 1
0 1 1 2
1 -2 3 0 0 0 0 10
1
0 5 5 8 0 0 0 10
1
-3 5 0 8 0 0 0 10
2
0 5 5 8
0 2 4 5 0 0 0 10
2
0 5 5 8
-2 1 0 4 0 0 0 10
2
0 0 5 8
-2 1 0 5 0 0 1 10
0 0 -1 2 1
3
-1 0 0 1
0 1 1 2
1 -2 3 0 0 -1 -1 0
9
-3 4 4 5
4 -3 5 5
-2 -3 4 -2
-3 -3 -2 4
-1 2 0 4
1 1 3 3
0 0 1 1
-2 -2 0 0
2 -2 3 0 0 0 0 0 结果应该为:
-1
3
2
1
0
0
0
0
2
1
1
5
*/

HDU 4444 Walk (离散化建图+BFS+记忆化搜索) 绝对经典的更多相关文章

  1. FZU 2092 收集水晶 bfs+记忆化搜索 or 暴力

    题目链接:收集水晶 一眼看过去,觉得是普通的bfs,初始位置有两个.仔细想了想...好像如果这样的话..........[不知道怎么说...T_T] dp[12][12][12][12][210] 中 ...

  2. HDU 1142 A Walk Through the Forest(Dijkstra+记忆化搜索)

    题意:看样子很多人都把这题目看错了,以为是求最短路的条数.真正的意思是:假设 A和B 是相连的,当前在 A 处, 如果 A 到终点的最短距离大于 B 到终点的最短距离,则可以从 A 通往 B 处,问满 ...

  3. [Swust OJ 409]--小鼠迷宫问题(BFS+记忆化搜索)

    题目链接:http://acm.swust.edu.cn/problem/409/ Time limit(ms): 1000 Memory limit(kb): 65535   Description ...

  4. FZU 2092 bfs+记忆化搜索

    晚上团队训练赛的题 和普通bfs不同的是 这是同时操纵人与影子两个单位进行的bfs 由于可能发生人和影子同时接触水晶 所以不可以分开操作 当时使用node记录人和影子的位置 然后进行两重for循环来分 ...

  5. luogu1514 [NOIp2010]引水入城 (bfs+记忆化搜索)

    我们先bfs一下看看是否能到最底下的所有点 如果不能的话,直接把不能到的那几个数一数就行了 如果能的话: 可以发现(并不可以)某格能到达的最底下的格子一定是一个连续的区间 (因为如果不连续的话,我们先 ...

  6. 【BZOJ 1415】 1415: [Noi2005]聪聪和可可 (bfs+记忆化搜索+期望)

    1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1640  Solved: 962 Description I ...

  7. csu 最优对称路径(bfs+记忆化搜索)

    1106: 最优对称路径 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 371  Solved: 77[Submit][Status][Web Boar ...

  8. hdu 1078 FatMouse and Cheese(简单记忆化搜索)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1078 题意:给出n*n的格子,每个各自里面有些食物,问一只老鼠每次走最多k步所能吃到的最多的食物 一道 ...

  9. hdu 4753 Fishhead’s Little Game 博弈论+记忆化搜索

    思路:状态最多有2^12,采用记忆化搜索!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm& ...

随机推荐

  1. css(二)

    重新排传智的首页!头部和左边的部分完成了! <!doctype html> <html lang="en"> <head> <meta c ...

  2. MySQL删除外键定义的方法

    MySQL外键在定以后,如果我们不再需要这个外键,可以进行删除操作,下面就为您介绍MySQL删除外键定义的方法,供您参考. 不知道大家有没有发现,在定义外键的时候articles.member_id外 ...

  3. 使用 AtomicInteger 进行计数(java多线程优化)

    通常,在我们实现多线程使用的计数器或随机数生成器时,会使用锁来保护共享变量.这样做的弊端是如果锁竞争的太厉害,会损害吞吐量,因为竞争的同步非常昂贵. volatile 变量虽然可以使用比同步更低的成本 ...

  4. gcc和g++编译c或者c++文件碰到的问题

    gcc和g++都是GNU(组织)的一个编译器.        误区一:gcc只能编译c代码,g++只能编译c++代码      两者都可以,但是请注意:      1.后缀为.c的,gcc把它当作是C ...

  5. Char Tools,方便的字符编码转换小工具

    工作关系,常有字符编码转换方面的需要,写了这个小工具 Char Tools是一款方便的字符编码转换小工具,基于.Net Framework 2.0 Winform开发 主要功能 URL编码:URLEn ...

  6. FreeMarker辅助

    /** * FreeMarker 辅助类 * @author Rubekid * */ public class FreeMarkerHelper { /** * 模板文件存放目录 */ privat ...

  7. 华硕笔记本怎么设置u盘启动(两种方法)

    华硕笔记本怎么设置u盘启动(两种方法) 华硕笔记本怎么设置u盘启动.我想用U盘安装系统但是 我不知道如何设置U盘启动,那么该如何设置呢?下面和大家分享一下我的经验,希望能够帮到大家.如果你的系统是预装 ...

  8. 随机获取oracle数据库中的任意一行数据(rownum)

    最近看oracle资料的时候,了解rownum的概念,以前只知道对数据库表进行简单的增删改查: 看到了rownum的概念后,突然想到了好多业务场景应该都可以适用的,比如在进行随机发奖的时候, 我们就可 ...

  9. js判断当前操作系统

    function validataOS(){ if(navigator.userAgent.indexOf(“Window”)>0){ return ”Windows”; }else if(na ...

  10. 对mysql进行分表

    1. 有某个自段进行md5散列,然后生成ord SCII码 $num = ord(md5($user)) //是一个数字 参考 $num/3 ,$num/4;如果我们不是严格意义上的分表,可以参考分布 ...