九野的博客,转载请注明出处 http://blog.csdn.net/acmmmm/article/details/10966383

开始建图打搓了,参考了大牛的题解打的版本比较清爽,后来改的基本雷同了http://www.cnblogs.com/woaishizhan/archive/2013/04/08/3008719.html

题意:给定n,m表示下面地图大小

.表示空地 #表示墙 *表示黄金

行走的路线是A->Z->a->z

规则,必须从字母依次走最短路到下一个字母(字母必须连续走,如果走不到下一个字母或者地图上不存在下一个字母则输出-1)

每次走到下一个字母可以取走路途上的一个黄金,问最多能取走几个黄金

思路:走到最后一个字母就结束了,所以希望从每个字母走出来都能得到一个黄金,所以是二分匹配

把起点字母作为X集, 黄金作为Y集, 映射条件是黄金在 字母间行走的最短路上

然后这里用BFS寻找路径建图

最后套个二分匹配的模版

  1. #include<stdio.h>
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<set>
  5. #include<math.h>
  6. #include<string.h>
  7. #include<queue>
  8. #include<vector>
  9. #define N 105
  10. #define inf 999999999
  11. using namespace std;
  12. int n,M;
  13. int road[N],p[N*N],gold[N*N],num,pn;//road 表示字母在p中的编号,p是字母的坐标(一维化)
  14. int dis[N][N*N];//dis[a][b] 表示离散化的字母点a到 一维化的坐标b的距离
  15. char map[N][N];
  16. vector<int>G[N];
  17.  
  18. int go[4][2]={1,0,0,1,-1,0,0,-1};
  19. void bfs(int s){
  20. bool vis[N*N];
  21. memset(vis,0,sizeof(vis));
  22. queue<int>q;
  23.  
  24. memset(dis[s],-1,sizeof(dis[s]));
  25. dis[s][p[s]]=0;
  26.  
  27. q.push(p[s]);
  28. vis[p[s]]=1;
  29. while(!q.empty())
  30. {
  31. int t=q.front();
  32. int x=t/M,y=t%M;
  33. q.pop() ;
  34. for(int i=0;i<4;i++)
  35. {
  36. int nowx=x+go[i][0],nowy=y+go[i][1];
  37. int now=nowx*M+nowy;
  38. if(map[nowx][nowy]=='#')continue;
  39. if(nowx<0 || nowx>=n ||nowy<0||nowy>=M)continue;
  40. if(vis[now])continue;
  41. vis[now]=1;
  42.  
  43. dis[s][now]=dis[s][t]+1;
  44. q.push(now);
  45. }
  46. }
  47. }
  48. int lef[N*N];//lef[v]表示右边点v 当前连接的点
  49. bool T[N*N];//右边的点是否连过
  50.  
  51. bool match(int x)
  52. {
  53. for(int i=0;i<G[x].size();i++)
  54. {
  55. int v=G[x][i];
  56. if(!T[v])
  57. {
  58. T[v]=true;
  59. if(lef[v]==-1||match(lef[v]))
  60. {
  61. lef[v]=x;
  62. return true;
  63. }
  64. }
  65. }
  66. return false;
  67. }
  68.  
  69. void solve()
  70. {
  71. int ans=0;
  72. memset(lef,-1,sizeof(lef));
  73. for(int i=0;i<pn-1;i++)//左右点集匹配,左点集是 0-(pn-1) 右点集是G[左点].size()
  74. {
  75. memset(T,0,sizeof(T));
  76.  
  77. if(match(i))ans++;
  78. }
  79. printf("%d\n",ans);
  80. }
  81.  
  82. int f(char c){
  83. if('A'<=c && c<='Z')return c-'A';
  84. else if('a'<=c && c<='z')return c-'a'+26;
  85. }
  86. int main(){
  87. int i,j;
  88. while(~scanf("%d%d",&n,&M)){
  89. pn=num=0;
  90. memset(road,-1,sizeof(road));//这句没有最后第二个案例过不了
  91. for(i=0;i<n;i++)
  92. {
  93. scanf("%s",map[i]);
  94. for(j=0;j<M;j++)
  95. if(isalpha(map[i][j]))
  96. {
  97. p[pn]=i*M+j;
  98. road[f(map[i][j])]=pn;
  99. pn++;
  100. }
  101. else if(map[i][j]=='*')
  102. {
  103. gold[num++]=i*M+j;
  104. }
  105. }
  106.  
  107. for(i=0;i<pn;i++)bfs(i),G[i].clear();
  108. for(i=0;i<pn-1;i++)
  109. {
  110. if(road[i]==-1||road[i+1]==-1) break;
  111. if(dis[road[i]][p[road[i+1]]]==-1) break;
  112. }
  113. if(i!=pn-1){puts("-1");continue;}
  114. for(i=0;i<pn-1;i++)
  115. for(j=0;j<num;j++)
  116. {
  117. if(dis[road[i]][gold[j]]==-1 || dis[road[i+1]][gold[j]]==-1)continue;//j这点的黄金到不了字母点
  118. if(dis[road[i]][gold[j]]+dis[road[i+1]][gold[j]]==dis[road[i]][p[road[i+1]]])
  119. G[i].push_back(j);
  120. }
  121. solve();
  122. }
  123. return 0;
  124. }
  125. /*
  126. 3 4
  127. A#B.
  128. ***C
  129. .D..
  130.  
  131. 4 4
  132. A#B.
  133. ***C
  134. .D..
  135. ..E*
  136.  
  137. 4 4
  138. A#B.
  139. ***C
  140. .D..
  141. .*E*
  142.  
  143. 4 4
  144. A#B.
  145. ***C
  146. .D#.
  147. .#E*
  148.  
  149. 4 4
  150. A#B.
  151. ***C
  152. .D#.
  153. .#E.
  154.  
  155. 4 4
  156. A#B.
  157. ***C
  158. .D##
  159. .#E.
  160.  
  161. 4 4
  162. A#B.
  163. ***C
  164. .D#*
  165. .#E.
  166.  
  167. 4 4
  168. a#b.
  169. ***c
  170. .d#*
  171. .#e.
  172.  
  173. 4 4
  174. A#B*
  175. *.*C
  176. ..D#
  177. E*..
  178.  
  179. ans;
  180. 3
  181. 3
  182. 4
  183. 4
  184. 3
  185. -1
  186. 4
  187. -1
  188. 4
  189.  
  190. */

HDU 3468 BFS+二分匹配的更多相关文章

  1. hdu 1281棋盘游戏(二分匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281   Problem Description 小希和Gardon在玩一个游戏:对一个N*M的棋盘, ...

  2. poj 3057(bfs+二分匹配)

    题目链接:http://poj.org/problem?id=3057 题目大概意思是有一块区域组成的房间,房间的边缘有门和墙壁,'X'代表墙壁,'D'代表门,房间内部的' . '代表空区域,每个空区 ...

  3. HDU 2819 Swap (二分匹配+破输出)

    题意:给定上一个01矩阵,让你变成一个对角全是 1 的矩阵. 析:二分匹配,把行和列看成两个集合,用匈牙利算法就可以解决,主要是在输出解,在比赛时一紧张不知道怎么输出了. 输出应该是要把 match[ ...

  4. hdu 3681(bfs+二分+状压dp判断)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 思路:机器人从出发点出发要求走过所有的Y,因为点很少,所以就能想到经典的TSP问题.首先bfs预 ...

  5. hdu 2119 Matrix(二分匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2119 Matrix Time Limit: 5000/1000 MS (Java/Others)    ...

  6. hdu 1281 棋盘游戏 (二分匹配)

    棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  7. HDU 2819 — Swap 二分匹配

    Swap Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  8. Fire Net HDU - 1045(二分匹配)

    把每一列中相邻的 .  缩为一个点 作为二分图的左边 把每一行中相邻的  .  缩为一个点 作为二分图的右边 然后求最大匹配即可 这题用匈牙利足够了...然而..我用了hk...有点大材小用的感觉// ...

  9. Hdu 1498 二分匹配

    50 years, 50 colors Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

随机推荐

  1. java如何把char型数据转换成int型数据(转)

    一字符串,String=“2324234535”:把第i个数取出来时是char型的:char temp=String.charAt(i)如何把char型转换成int型?我需要求个尾数之和,如:123的 ...

  2. BZOJ 1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场

    题目 1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 491  S ...

  3. PPTPD服务端搭建

    http://www.360doc.com/content/14/0304/09/15165033_357558764.shtml . apt-get update; apt-get install ...

  4. ThinkPHP - 前置操作+后置操作

    前置操作和后置操作   系统会检测当前操作(不仅仅是index操作,其他操作一样可以使用)是否具有前置和后置操作,如果存在就会按照顺序执行,前置和后置操作的方法名是在要执行的方法前面加 _before ...

  5. 写一方法用来计算1+2+3+...n,其中n作为参数输入,返回值可以由方法名返回,也可以由参数返回

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. Linux内核态抢占机制分析(转)

    Linux内核态抢占机制分析  http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive ...

  7. 2014 HDU多校弟八场H题 【找规律把】

    看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决, ...

  8. Windows Phone 8初学者开发—第17部分:Coding4Fun工具包简介

    原文 Windows Phone 8初学者开发—第17部分:Coding4Fun工具包简介 第17部分:Coding4Fun工具包简介 原文地址:  http://channel9.msdn.com/ ...

  9. Automake创建项目

    autoconf和automake可以方便的构建linux下项目,一个简单的automake项目实例,麻雀虽小五脏俱全,以后无外乎在这基础上扩展相应的宏完善而已. .首先建立项目目录树 )创建目录树 ...

  10. Python 第六篇(中):面向对象编程中级篇

    面向对象编程中级篇: 编程思想概述: 面向过程:根据业务逻辑从上到下写垒代码  #最low,淘汰 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 #混口饭吃 def add(ho ...