[Bzoj ]2150 部落战争

2150: 部落战争(二分图匹配...)

Description

lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土。 A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住。lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头。途中只能经过城镇,不能经过高山深涧。 2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了。 3. 每支军队都可以在任意一个城镇停止征战。 4. 所有军队都很奇怪,他们走的方法有点像国际象棋中的马。不过马每次只能走1*2的路线,而他们只能走R*C的路线。 lanzerb的野心使得他的目标是统一全国,但是兵力的限制使得他们在配备人手时力不从心。假设他们每支军队都能顺利占领这支军队经过的所有城镇,请你帮lanzerb算算至少要多少支军队才能完成统一全国的大业。

Input

第一行包含4个整数M、N、R、C,意义见问题描述。接下来M行每行一个长度为N的字符串。如果某个字符是‘.‘,表示这个地方是城镇;如果这个字符时‘x‘,表示这个地方是高山深涧。

Output

输出一个整数,表示最少的军队个数。

Sample Input

【样例输入一】

3 3 1 2

...

.x.

...

【样例输入二】

5 4 1 1

....

..x.

...x

....

x...

Sample Output

【样例输出一】

4

【样例输出二】

5

【样例说明】

【数据范围】

100%的数据中,1<=M,N<=50,1<=R,C<=10。

最近刷的二分图匹配类型的题有点多==

  这道题就是一个典型的二分图匹配==

    貌似跟CodeVS 1904有点像...

      这道题能在1h内A掉对我这种大蒟蒻真是莫大的鼓舞~

        这道题就是将所有的可行的点连一条边....当然是从上向下连一条有向边...然后...给每个点标号,然后跑一波二分图匹配==当然,下一个点也要判断是否x

代码如下~、

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=2610;
 6 int G[maxn][maxn],y[maxn],num[maxn][maxn];
 7 bool vis[maxn],f[maxn][maxn];
 8 int dx[5],dy[5];
 9 int n,m,r,c,id;
10 char s[501];
11 long long ans;
12 bool dfs(int u){
13     for(int i=1;i<=id;i++)
14         if(G[u][i]&&!vis[i]){
15             vis[i]=1;
16                 if(!y[i]||dfs(y[i])){
17                     y[i]=u;
18                     return 1;
19                 }
20         }
21     return 0;
22 }
23 int main(){
24     scanf("%d%d%d%d",&n,&m,&r,&c);
25         dx[0]=r;dx[1]=r;dx[2]=c;dx[3]=c;
26         dy[0]=c;dy[1]=-c;dy[2]=r;dy[3]=-r;
27     for(int i=1;i<=n;i++){
28         scanf("%s",s);
29             for(int j=0;j<m;j++){
30                 if(s[j]==‘.‘) f[i][j+1]=1,num[i][j+1]=++id;
31             }
32     }
33     for(int i=1;i<=n;i++)
34         for(int j=1;j<=m;j++)
35             if(f[i][j]) for(int k=0;k<4;k++){
36                     int x=i+dx[k],y=j+dy[k];
37                     if(x<1||x>n||y<1||y>m) continue;
38                     if(f[x][y])    G[num[i][j]][num[x][y]]=1;
39                 }
40     for(int i=1;i<=id;i++){
41         memset(vis,0,sizeof(vis));
42             if(dfs(i)) ans++;
43     }
44     printf("%d\n",id-ans);
45 }

又臭又长~

时间: 2024-08-03 11:42:09

[Bzoj ]2150 部落战争的相关文章

BZOJ 2150 部落战争(最小路径覆盖)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2150 题意:一个n*m的国家,有些是障碍.对于一支军队,每次只能走C*R的格式(比如马是走1*2的格式),而且只能从上往下走.每个格子只能被一个军队经过.问最少需要多少军队可以遍历完所有格子? 思路:上下能连边的连边.最后就是最小路径覆盖. int a[N][N],n,m; char s[55][55]; int ID(int i,int j) { return (i-1)*m+j;

BZOJ 2150: 部落战争 最大流

2150: 部落战争 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=2150 Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇

BZOJ 2150 部落战争 最小路径覆盖 二分图最大匹配

题目大意:给出一张地图,一个军队要征战整个土地.一块土地只能经过一次,有X的地方不能走,军队只会走R*C个格子,只会向下走,问最少需要多少军队能够征战所有的土地. 思路:这个是前几天考试的题,今天居然发现时BZ的原题,还好当时A掉了... 看到每个土地只能经过一次就想到了网络流什么的,再一想想好像是最小路径覆盖啊,然后拆点,建图,Hungary,二分图最小路径覆盖=点数-最大匹配,没了.. CODE: #include <cstdio> #include <cstring> #in

BZOJ2150: 部落战争

题解: 把每个点拆成入点和出点,因为必须经过一次且只能经过一次.所以在两个点之间连一条上界=下界=1的边. 然后再s到每个入点连边,每个出点向t连边,点与点之间... 求最小流就可以过了... (感觉最小流神一般的存在...) 代码: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #inclu

BZOJ-2150部落战争(最小路径覆盖)

2150: 部落战争 Time Limit: 10 Sec  Memory Limit: 259 MB Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头.途中只能经过城镇,不能经过高山深涧. 2. 如果某个城镇被某支军队到过,则

(拆点+最小路径覆盖) bzoj 2150

2150: 部落战争 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 518  Solved: 298[Submit][Status][Discuss] Description lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从

bzoj2150: 部落战争(匈牙利)

2150: 部落战争 题目:传送门 题解: 辣鸡数据..毁我AC率 先说做法,很容易就可以看出是二分图匹配的最小路径覆盖(可能是之前不久刚做过类似的题) 一开始还傻逼逼的去直接连边然后准备跑floyd...肯定是做祭祀做傻了 二分图嘛,将每个点拆成两个集合再连啊... 然后最小路径覆盖=总点数-最大匹配数 强烈吐槽!个人习惯用数组存点编号...50*50的数据范围我开55*55...结果WA n次 然后...改成56*56...AC...ORZ 代码: 1 #include<cstdio> 2

BZOJ 1821 部落划分(二分+并查集)

答案是具有单调性的. 因为最近的两个部落的距离为mid,所以要是有两个野人的距离<mid,则他们一定是一个部落的. 用并查集维护各联通块,如果最后的联通块个数>=k,那么mid还可以再小点.如果<k,mid还可以再大点. 二分搞一搞就行了. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector&

【bzoj2150】部落战争 有上下界最小流

题目描述 lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头.途中只能经过城镇,不能经过高山深涧. 2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了. 3. 每支军队都可以在任意一个城镇停止征战. 4. 所有军队都很奇怪,他们走的方法有点像