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

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

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

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

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

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

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

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

AC代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <string>
  5. #include <cstdlib>
  6. #include <cmath>
  7. #include <vector>
  8. #include <list>
  9. #include <deque>
  10. #include <queue>
  11. #include <iterator>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <algorithm>
  16. #include <cctype>
  17. #include <sstream>
  18. using namespace std;
  19.  
  20. typedef long long LL;
  21. const int N=410;
  22. const LL II=100000000;
  23. const int INF=0x3f3f3f3f;
  24. const int M=12345678;
  25. const double PI=acos(-1.0);
  26.  
  27. int sx,sy,ex,ey;
  28. int si,sj,ei,ej;
  29. int n,nx,ny;
  30. int x[N],y[N];
  31. int g[N][N],step[N][N];
  32. int t[4][2]={1,0,-1,0,0,1,0,-1};
  33.  
  34. struct node
  35. {
  36. int x1,x2,y1,y2;
  37. }rect[N];
  38.  
  39. struct xiaohao
  40. {
  41. int xx,yy;
  42. int step;
  43. }e,w,xh[M];
  44.  
  45. int nextint()
  46. {
  47. int f=1;
  48. char c;
  49. while((c=getchar())<'0'||c>'9')
  50. if(c=='-')
  51. f=-1;
  52. int sum=c-'0';
  53. while((c=getchar())>='0'&&c<='9')
  54. sum=sum*10+c-'0';
  55. return sum*f;
  56. }
  57.  
  58. void lisanhua(int m) //离散化
  59. {
  60. int i,j;
  61. sort(x+1,x+m+1);
  62. sort(y+1,y+m+1);
  63. nx=1;
  64. for(i=2;i<=m;i++)//去重
  65. if(x[i]!=x[i-1])
  66. x[++nx]=x[i];
  67. ny=1;
  68. for(i=2;i<=m;i++)//去重
  69. if(y[i]!=y[i-1])
  70. y[++ny]=y[i];
  71. }
  72.  
  73. int getx(int xx)//数据量大的时候可以用二分查找
  74. {
  75. for(int i=1;i<=nx;i++)
  76. if(x[i]==xx)
  77. return i;
  78. }
  79.  
  80. int gety(int yy)
  81. {
  82. for(int i=1;i<=ny;i++)
  83. if(y[i]==yy)
  84. return i;
  85. }
  86.  
  87. void add(int x1,int x2,int y1,int y2)
  88. {
  89. int i,j;
  90. for(i=x1;i<=x2;i++)
  91. for(j=y1;j<=y2;j++)
  92. g[i][j]=1;//建筑物标记为1
  93. }
  94.  
  95. void jiantu()
  96. {
  97. int i,j,x1,x2,y1,y2;
  98. memset(g,0,sizeof(g));
  99. si=getx(sx);
  100. sj=gety(sy);
  101. ei=getx(ex);
  102. ej=gety(ey);
  103.  
  104. for(i=si*3;i>=si*3-2;i--)//起点,这个地方9个格子全部要标记为5
  105. for(j=sj*3;j>=sj*3-2;j--)
  106. g[i][j]=5;
  107. for(i=ei*3;i>=ei*3-2;i--)//终点,这个地方9个格子全部要标记为6
  108. for(j=ej*3;j>=ej*3-2;j--)
  109. g[i][j]=6;
  110.  
  111. for(i=1;i<=n;i++)
  112. {
  113. x1=getx(rect[i].x1);
  114. y1=gety(rect[i].y1);
  115. x2=getx(rect[i].x2);
  116. y2=gety(rect[i].y2);
  117.  
  118. add(x1*3,x2*3-2,y1*3,y2*3-2);
  119. }
  120. for(i=1;i<=nx;i++)//将重合的点中间补上
  121. for(j=1;j<=ny;j++)
  122. {
  123. 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)
  124. g[i*3-1][j*3-1]=1;
  125. if(g[i*3-1][j*3-2]==1&&g[i*3-1][j*3]==1)
  126. g[i*3-1][j*3-1]=1;
  127. if(g[i*3-2][j*3-1]==1&&g[i*3][j*3-1]==1)
  128. g[i*3-1][j*3-1]=1;
  129. }
  130. // for(i=1;i<=3*nx;i++) //输出离散化后的图
  131. // {
  132. // for(j=1;j<=3*ny;j++)
  133. // printf("%d",g[i][j]);
  134. // printf("\n");
  135. // }
  136. }
  137.  
  138. bool ok(int tx,int ty)
  139. {
  140. return (tx>=0&&tx<=3*nx&&ty>=0&&ty<=3*ny);
  141. }
  142.  
  143. void BFS()
  144. {
  145. int i,j,head=0,tail=0;
  146. w.step=-1;
  147. for(i=si*3;i>=si*3-2;i--)
  148. for(j=sj*3;j>=sj*3-2;j--)
  149. if(g[i][j]==5)
  150. {
  151. w.xx=i;w.yy=j;
  152. xh[tail++]=w;
  153. }
  154. memset(step,INF,sizeof(step));
  155. step[w.xx][w.yy]=-1;
  156. while(head!=tail)
  157. {
  158. e=xh[head++];
  159. if(head==M)
  160. head=0;
  161. for(i=0;i<4;i++)
  162. {
  163. w=e;
  164. w.step++;
  165. int tx=w.xx+t[i][0];
  166. int ty=w.yy+t[i][1];
  167. while(ok(tx,ty)&&g[tx][ty]!=1)//判断是否在界内,而且能走
  168. {
  169. if(w.step<step[tx][ty])
  170. {
  171. if(g[tx][ty]==6)
  172. {
  173. printf("%d\n",w.step);
  174. return ;
  175. }
  176. step[tx][ty]=w.step;
  177. w.xx=tx;
  178. w.yy=ty;
  179. xh[tail++]=w;
  180. if(tail==M)
  181. tail=0;
  182. }
  183. tx+=t[i][0];
  184. ty+=t[i][1];
  185. }
  186. }
  187. }
  188. printf("-1\n");
  189. }
  190.  
  191. int main()
  192. {
  193. int i,j;
  194. while(scanf("%d%d%d%d",&sx,&sy,&ex,&ey))
  195. {
  196. int x1,x2,y1,y2,m;
  197. if((!sx)&&(!sy)&&(!ex)&&(!ey))
  198. break;
  199. if(sx==ex&&sy==ey)
  200. {
  201. printf("0\n");
  202. continue;
  203. }
  204. m=0;
  205. rect[0].x1=x[++m]=sx;
  206. rect[0].y1=y[m]=sy;
  207. rect[0].x2=x[++m]=ex;
  208. rect[0].y2=y[m]=ey;
  209. scanf("%d",&n);
  210. for(i=1;i<=n;i++)
  211. {
  212. scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
  213. if(x1>x2)//防止有的数据先是右上点再是左下点
  214. swap(x1,x2),swap(y1,y2);
  215.  
  216. x[++m]=rect[i].x1=x1;
  217. y[m]=rect[i].y1=y1;
  218. x[++m]=rect[i].x2=x2;
  219. y[m]=rect[i].y2=y2;
  220. }
  221.  
  222. lisanhua(m);
  223. jiantu();
  224. BFS();
  225. }
  226. return 0;
  227. }
  228.  
  229. /*
  230. 0 0 3 3
  231. 4
  232. 2 0 4 2
  233. 0 2 2 4
  234. 4 2 6 4
  235. 2 4 4 6
  236.  
  237. 100 -50 10 20
  238. 4
  239. -100 15 -20 30
  240. -5 25 50 100
  241. -30 -30 70 -20
  242. 70 -20 120 80
  243.  
  244. 5 -1 60 7
  245. 3
  246. 1 8 101 888
  247. 0 0 49 5
  248. 50 0 100 6
  249.  
  250. 0 -1 2 1
  251. 3
  252. -1 0 0 1
  253. 0 1 1 2
  254. 1 -2 3 0
  255.  
  256. 0 0 0 10
  257. 1
  258. 0 5 5 8
  259.  
  260. 0 0 0 10
  261. 1
  262. -3 5 0 8
  263.  
  264. 0 0 0 10
  265. 2
  266. 0 5 5 8
  267. 0 2 4 5
  268.  
  269. 0 0 0 10
  270. 2
  271. 0 5 5 8
  272. -2 1 0 4
  273.  
  274. 0 0 0 10
  275. 2
  276. 0 0 5 8
  277. -2 1 0 5
  278.  
  279. 0 0 1 10
  280. 0
  281.  
  282. 0 -1 2 1
  283. 3
  284. -1 0 0 1
  285. 0 1 1 2
  286. 1 -2 3 0
  287.  
  288. 0 -1 -1 0
  289. 9
  290. -3 4 4 5
  291. 4 -3 5 5
  292. -2 -3 4 -2
  293. -3 -3 -2 4
  294. -1 2 0 4
  295. 1 1 3 3
  296. 0 0 1 1
  297. -2 -2 0 0
  298. 2 -2 3 0
  299.  
  300. 0 0 0 0
  301.  
  302. 结果应该为:
  303. -1
  304. 3
  305. 2
  306. 1
  307. 0
  308. 0
  309. 0
  310. 0
  311. 2
  312. 1
  313. 1
  314. 5
  315. */

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. Linux下的bc计算器

    bc = basic calculator scale:设置精度,默认为0 obase:设置输出进制,默认为10 ibase:设置输入进制,默认为10 原文:http://www.linuxidc.c ...

  2. 性能优化之NSDateFormatter

    为什么要优化NSDateFormatter? 优化方式有哪些? 为什么要优化NSDateFormatter? 首先,过度的创建NSDateFormatter用于NSDate与NSString之间转换, ...

  3. 获取布局 ActionBar

    LayoutInflater inflater = getLayoutInflater();View imageLayout = inflater.inflate(R.layout.preferenc ...

  4. 【Android】Activity的菜单机制和方法解析

    Activity有一套机制来实现对菜单的管理,方法如下: 1. 初始化菜单 public boolean onCreateOptionsMenu(Menu menu) 此方法用于初始化菜单,其中men ...

  5. Java基础知识强化66:基本类型包装类之JDK5新特性自动装箱和拆箱

    1. JDK1.5以后,简化了定义方式. (1)Integer  x = new  Integer(4):可以直接写成如下:         Integer  x = 4 ://自动装箱,通过valu ...

  6. Excel02-快速无误输入多个零

    第一步:设置单元格格式-->小数位数为0,货币符号为¥ 第二步:在单元格输入数据:1**5回车即显示为¥100,000 **N 表示后面有N个零,会自动加入我们设置的货币符号¥ 这对我们在输入巨 ...

  7. POJ 2318 TOYS/POJ 2398 Toy Storage

    计算几何终于开坑了... 叉积+二分. #include<iostream> #include<cstdio> #include<cstring> #include ...

  8. Swift - 43 - 继承, 多态, 析构函数

    import Foundation /* 什么叫继承: 可以简单理解为一个类可以从它的父类或者基类中直接拿属性或者方法去使用 冒号":"表示两者之间的继承关系 */ class P ...

  9. C# 前台线程与后台线程区别

    using System; using System.Drawing; using System.Windows.Forms; using System.Threading; namespace Wi ...

  10. Slony-I双机备份

    测试环境:postgresql 9.3.5,slony-I2.2.3(application stack builder提供)以下参考网上教程亲自测试总结 ---------------------- ...