//给一个n*m的图
//.表示空白地
//*表示有黄金
//#表示墙
//一个人须要依照A...Z..a..z的顺序以最短路径走到下一个
//每次仅仅能在他的路线上经过的地方取一块黄金
//问最多能取多少黄金
//对于每次起点和终点,用bfs搜索最短路,再用dfs找出最短路线经过的全部点
//对于第i次找最短路线与其走过的点建立边,然后用二分匹配就能找出
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std ;
const int maxn = 110 ;
vector<int> vec[maxn] ;
int match[maxn*maxn] ;
int vis[maxn][maxn] ;
int visit[maxn*maxn] ;
char map[maxn][maxn] ;
int pos[maxn*maxn] ;int len ;
int st_x , st_y , en_x, en_y ;
int dx[4] = {0 , 1 , 0 , -1} ;
int dy[4] = {1 , 0 , -1 , 0} ;
int n , m ;
queue<int> que ;
int sum = 0 ;
void dfs(int x , int y , int num)
{
sum++ ;
if(x == st_x && y == st_y)
return ;
if(map[x][y] == '*')
vec[num].push_back(x*m+y) ;
for(int i = 0;i < 4;i++)
{
int nx = x + dx[i] ;
int ny = y + dy[i] ;
if(nx < 0 || nx >= n || ny < 0 || ny >= m || vis[nx][ny] + 1 != vis[x][y])
continue ;
dfs(nx , ny ,num);
}
vis[x][y] = 0 ;
}
int bfs(int num)
{
while(que.size())que.pop() ;
memset(vis, 0 ,sizeof(vis)) ;
que.push(st_x) ;que.push(st_y) ;
vis[st_x][st_y] = 1;
while(que.size())
{
int x = que.front() ; que.pop() ;
int y = que.front() ; que.pop() ;
if(x == en_x && y == en_y)
{
dfs(x , y ,num) ;
return true ;
}
int step = vis[x][y] ;
for(int i = 0;i < 4;i++)
{
int nx = dx[i] + x ;
int ny = dy[i] + y ;
if(nx < 0 || nx >= n || ny < 0 || ny >= m || vis[nx][ny] || map[nx][ny] == '#')
continue ;
vis[nx][ny] = vis[x][y] + 1 ;
que.push(nx);
que.push(ny) ;
}
}
return false ;
}
int find(int u)
{
for(int i = 0;i < vec[u].size() ;i++)
{
int v = vec[u][i] ;
if(!visit[v])
{
visit[v] = 1 ;
if(match[v] == -1 || find(match[v]))
{
match[v] = u ;
return true ;
}
}
}
return false ;
}
int Match()
{
int ans = 0 ;
memset(match , -1 , sizeof(match)) ;
for(int i = 0;i < len - 1;i++)
{
memset(visit ,0 , sizeof(visit)) ;
if(find(i))
ans++ ;
}
return ans ;
}
int main()
{
//freopen("in.txt" ,"r" , stdin) ;
while(~scanf("%d%d" ,&n , &m))
{
memset(pos ,0 , sizeof(pos)) ;
len = 0 ;
for(int i = 0;i < n;i++)
{
scanf("%s" , &map[i]) ;
for(int j = 0;j < m;j++)
if((map[i][j] >= 'a'&&map[i][j] <='z'))
pos[map[i][j]-'a'+26] = i*m + j +1,len++ ;
else if(map[i][j] >= 'A' && map[i][j] <= 'Z')
pos[map[i][j]-'A'] = i*m + j + 1, len++ ;
}
int flag = 0 ;
for(int i = 0;i < len;i++)
{
if(!pos[i])
flag = 1 ;
pos[i]--;
}
if(len < 2 || flag)
{
puts("-1");
continue ;
}
for(int i = 0;i < len - 1;i++)
{
vec[i].clear() ;
st_x = pos[i]/m;st_y = pos[i]%m;
en_x = pos[i+1]/m;en_y = pos[i+1]%m ;
if(!bfs(i))
{
flag = 1;
break ;
}
}
if(flag)puts("-1") ;
else
printf("%d\n" , Match()) ;
}
return 0 ;
}

hdu3468 Treasure Hunting 二分匹配的更多相关文章

  1. poj 2594 Treasure Exploration (二分匹配)

    Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 6558   Accepted: 2 ...

  2. kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树

    二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j ...

  3. POJ 1274 The Perfect Stall、HDU 2063 过山车(最大流做二分匹配)

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24081   Accepted: 106 ...

  4. [kuangbin带你飞]专题十 匹配问题 二分匹配部分

    刚回到家 开了二分匹配专题 手握xyl模板 奋力写写写 终于写完了一群模板题 A hdu1045 对这个图进行 行列的重写 给每个位置赋予新的行列 使不能相互打到的位置 拥有不同的行与列 然后左行右列 ...

  5. BZOJ 1189 二分匹配 || 最大流

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1155  Solved: 420[Submi ...

  6. Kingdom of Obsession---hdu5943(二分匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5943 题意:给你两个数n, s 然后让你判断是否存在(s+1, s+2, s+3, ... , s+n ...

  7. poj 2060 Taxi Cab Scheme (二分匹配)

    Taxi Cab Scheme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5710   Accepted: 2393 D ...

  8. [ACM_图论] Sorting Slides(挑选幻灯片,二分匹配,中等)

    Description Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he i ...

  9. [ACM_图论] The Perfect Stall 完美的牛栏(匈牙利算法、最大二分匹配)

    描述 农夫约翰上个星期刚刚建好了他的新牛棚,他使用了最新的挤奶技术.不幸的是,由于工程问题,每个牛栏都不一样.第一个星期,农夫约翰随便地让奶牛们进入牛栏,但是问题很快地显露出来:每头奶牛都只愿意在她们 ...

随机推荐

  1. Django REST Framework 序列化和校验 知识点

    DRF序列化 Django ORM对象 --> JSON格式的数据 序列化 JSON格式的数据 --> Django ORM数据 反序列化 需要两个工具: from rest_framew ...

  2. oracle 数据类型及函数

    第一节:字符串类型及函数 字符类型分 3 种,char(n) .varchar(n).varchar2(n) : char(n)固定长度字符串,假如长度不足 n,右边空格补齐: varchar(n)可 ...

  3. Git学习总结(9)——如何构建你自己的 Git 服务器

    现在我们将开始学习如何构建一个Git服务器,如何在具体的事件中写一个针对特定的触发操作的自定义Git(例如通告),如何发布你的代码到一个网站. 目前为止,用户对Git的焦点主要在Git的使用上.这篇文 ...

  4. 在Action中获取servlet API

    Struts2的Action组件是不依赖servlet API 的.那么当你在action中的业务需要处理HttpServletRequest和HttpServletResponse的时候(比如要对响 ...

  5. 数据库范式1NF 2NF 3NF BCNF(实例)通俗易懂的讲解

    [转] 数据库范式1NF 2NF 3NF BCNF(实例)通俗易懂的讲解     本文对大多数初学数据库原理的同学绝对是个大福利,哈哈,完完整整的看完此篇博文一定能够清晰地理解数据库的四大范式.    ...

  6. Java二维码打印

    http://blog.csdn.net/OnePersonTZ/article/details/66560513

  7. Android自己定义百度地图缩放图标

    自己定义实现Android百度地图的缩放图标,须要自己定义一个缩放控件,实现效果例如以下: 这里的缩放效果,实现了点击button能够对地图的放大缩小,通过手势放大与缩小也控制缩放图标的可用状态.详细 ...

  8. Socket实现一个简单的半双工通信

    Socket是client进行在网络与server进行数据交互的一种基本通信方式.通信有三种通信.即单工.半双工,和全双工. 所谓单工,就是仅仅可以进行单向通信,如bb机. 而半双工就是一来一回的通信 ...

  9. HDU 5187 zhx&#39;s contest(防爆__int64 )

    Problem Description As one of the most powerful brushes, zhx is required to give his juniors n probl ...

  10. lambda的函数式接口

    函数式接口就是只包含一个抽象方法的接口A(不包括默认抽象方法,但包括继承来的方法):这个接口用来作为一个可变作用的方法B的参数.函数式接口的抽象方法的参数类型和返回值就是一套签名,这个签名叫做函数描述 ...