HDU 3468 BFS+二分匹配
九野的博客,转载请注明出处 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寻找路径建图
最后套个二分匹配的模版
- #include<stdio.h>
- #include<algorithm>
- #include<iostream>
- #include<set>
- #include<math.h>
- #include<string.h>
- #include<queue>
- #include<vector>
- #define N 105
- #define inf 999999999
- using namespace std;
- int n,M;
- int road[N],p[N*N],gold[N*N],num,pn;//road 表示字母在p中的编号,p是字母的坐标(一维化)
- int dis[N][N*N];//dis[a][b] 表示离散化的字母点a到 一维化的坐标b的距离
- char map[N][N];
- vector<int>G[N];
- int go[4][2]={1,0,0,1,-1,0,0,-1};
- void bfs(int s){
- bool vis[N*N];
- memset(vis,0,sizeof(vis));
- queue<int>q;
- memset(dis[s],-1,sizeof(dis[s]));
- dis[s][p[s]]=0;
- q.push(p[s]);
- vis[p[s]]=1;
- while(!q.empty())
- {
- int t=q.front();
- int x=t/M,y=t%M;
- q.pop() ;
- for(int i=0;i<4;i++)
- {
- int nowx=x+go[i][0],nowy=y+go[i][1];
- int now=nowx*M+nowy;
- if(map[nowx][nowy]=='#')continue;
- if(nowx<0 || nowx>=n ||nowy<0||nowy>=M)continue;
- if(vis[now])continue;
- vis[now]=1;
- dis[s][now]=dis[s][t]+1;
- q.push(now);
- }
- }
- }
- int lef[N*N];//lef[v]表示右边点v 当前连接的点
- bool T[N*N];//右边的点是否连过
- bool match(int x)
- {
- for(int i=0;i<G[x].size();i++)
- {
- int v=G[x][i];
- if(!T[v])
- {
- T[v]=true;
- if(lef[v]==-1||match(lef[v]))
- {
- lef[v]=x;
- return true;
- }
- }
- }
- return false;
- }
- void solve()
- {
- int ans=0;
- memset(lef,-1,sizeof(lef));
- for(int i=0;i<pn-1;i++)//左右点集匹配,左点集是 0-(pn-1) 右点集是G[左点].size()
- {
- memset(T,0,sizeof(T));
- if(match(i))ans++;
- }
- printf("%d\n",ans);
- }
- int f(char c){
- if('A'<=c && c<='Z')return c-'A';
- else if('a'<=c && c<='z')return c-'a'+26;
- }
- int main(){
- int i,j;
- while(~scanf("%d%d",&n,&M)){
- pn=num=0;
- memset(road,-1,sizeof(road));//这句没有最后第二个案例过不了
- for(i=0;i<n;i++)
- {
- scanf("%s",map[i]);
- for(j=0;j<M;j++)
- if(isalpha(map[i][j]))
- {
- p[pn]=i*M+j;
- road[f(map[i][j])]=pn;
- pn++;
- }
- else if(map[i][j]=='*')
- {
- gold[num++]=i*M+j;
- }
- }
- for(i=0;i<pn;i++)bfs(i),G[i].clear();
- for(i=0;i<pn-1;i++)
- {
- if(road[i]==-1||road[i+1]==-1) break;
- if(dis[road[i]][p[road[i+1]]]==-1) break;
- }
- if(i!=pn-1){puts("-1");continue;}
- for(i=0;i<pn-1;i++)
- for(j=0;j<num;j++)
- {
- if(dis[road[i]][gold[j]]==-1 || dis[road[i+1]][gold[j]]==-1)continue;//j这点的黄金到不了字母点
- if(dis[road[i]][gold[j]]+dis[road[i+1]][gold[j]]==dis[road[i]][p[road[i+1]]])
- G[i].push_back(j);
- }
- solve();
- }
- return 0;
- }
- /*
- 3 4
- A#B.
- ***C
- .D..
- 4 4
- A#B.
- ***C
- .D..
- ..E*
- 4 4
- A#B.
- ***C
- .D..
- .*E*
- 4 4
- A#B.
- ***C
- .D#.
- .#E*
- 4 4
- A#B.
- ***C
- .D#.
- .#E.
- 4 4
- A#B.
- ***C
- .D##
- .#E.
- 4 4
- A#B.
- ***C
- .D#*
- .#E.
- 4 4
- a#b.
- ***c
- .d#*
- .#e.
- 4 4
- A#B*
- *.*C
- ..D#
- E*..
- ans;
- 3
- 3
- 4
- 4
- 3
- -1
- 4
- -1
- 4
- */
HDU 3468 BFS+二分匹配的更多相关文章
- hdu 1281棋盘游戏(二分匹配)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 Problem Description 小希和Gardon在玩一个游戏:对一个N*M的棋盘, ...
- poj 3057(bfs+二分匹配)
题目链接:http://poj.org/problem?id=3057 题目大概意思是有一块区域组成的房间,房间的边缘有门和墙壁,'X'代表墙壁,'D'代表门,房间内部的' . '代表空区域,每个空区 ...
- HDU 2819 Swap (二分匹配+破输出)
题意:给定上一个01矩阵,让你变成一个对角全是 1 的矩阵. 析:二分匹配,把行和列看成两个集合,用匈牙利算法就可以解决,主要是在输出解,在比赛时一紧张不知道怎么输出了. 输出应该是要把 match[ ...
- hdu 3681(bfs+二分+状压dp判断)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 思路:机器人从出发点出发要求走过所有的Y,因为点很少,所以就能想到经典的TSP问题.首先bfs预 ...
- hdu 2119 Matrix(二分匹配)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2119 Matrix Time Limit: 5000/1000 MS (Java/Others) ...
- hdu 1281 棋盘游戏 (二分匹配)
棋盘游戏 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 2819 — Swap 二分匹配
Swap Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- Fire Net HDU - 1045(二分匹配)
把每一列中相邻的 . 缩为一个点 作为二分图的左边 把每一行中相邻的 . 缩为一个点 作为二分图的右边 然后求最大匹配即可 这题用匈牙利足够了...然而..我用了hk...有点大材小用的感觉// ...
- Hdu 1498 二分匹配
50 years, 50 colors Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
随机推荐
- java如何把char型数据转换成int型数据(转)
一字符串,String=“2324234535”:把第i个数取出来时是char型的:char temp=String.charAt(i)如何把char型转换成int型?我需要求个尾数之和,如:123的 ...
- BZOJ 1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场
题目 1619: [Usaco2008 Nov]Guarding the Farm 保卫牧场 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 491 S ...
- PPTPD服务端搭建
http://www.360doc.com/content/14/0304/09/15165033_357558764.shtml . apt-get update; apt-get install ...
- ThinkPHP - 前置操作+后置操作
前置操作和后置操作 系统会检测当前操作(不仅仅是index操作,其他操作一样可以使用)是否具有前置和后置操作,如果存在就会按照顺序执行,前置和后置操作的方法名是在要执行的方法前面加 _before ...
- 写一方法用来计算1+2+3+...n,其中n作为参数输入,返回值可以由方法名返回,也可以由参数返回
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Linux内核态抢占机制分析(转)
Linux内核态抢占机制分析 http://blog.sina.com.cn/s/blog_502c8cc401012pxj.html 摘 要]本文首先介绍非抢占式内核(Non-Preemptive ...
- 2014 HDU多校弟八场H题 【找规律把】
看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决, ...
- Windows Phone 8初学者开发—第17部分:Coding4Fun工具包简介
原文 Windows Phone 8初学者开发—第17部分:Coding4Fun工具包简介 第17部分:Coding4Fun工具包简介 原文地址: http://channel9.msdn.com/ ...
- Automake创建项目
autoconf和automake可以方便的构建linux下项目,一个简单的automake项目实例,麻雀虽小五脏俱全,以后无外乎在这基础上扩展相应的宏完善而已. .首先建立项目目录树 )创建目录树 ...
- Python 第六篇(中):面向对象编程中级篇
面向对象编程中级篇: 编程思想概述: 面向过程:根据业务逻辑从上到下写垒代码 #最low,淘汰 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 #混口饭吃 def add(ho ...