bzoj2150 部落战争
来源:互联网 发布:棋牌游戏算法 编辑:程序博客网 时间:2024/04/28 01:03
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。
从题意中很容易看出这是最小路径覆盖……因为从任意点出发到任意点停止,而且没有环
第一次做最小路径覆盖。自己yy了一下,应该要拆点。后来无论怎么连边也没法搞。
比如我要这样连:(图中所有边容量为1)
那么我要使1和1‘,2和2’,3和3‘之间的边保证满流,代表全图都已经覆盖,然后S到T的最大流尽量小。这好像可以用有上下界的网络流搞定,但是太麻烦了
去百度了一下,结果发现其实把它拆点搞成二分图,然后互相连边求最大匹配,那么tot-ans就是答案。我原来一直想着用最大流表示答案,然后各种斯巴达……
我觉得这还是很好理解的。最坏情况下覆盖全图需要n次,每次只覆盖一个点,现在最大匹配中两个点i,j匹配,代表有两个点可以缩成一个点,就是覆盖了i之后可以直接接着覆盖j,,所以答案-1。
#include<cstdio>#include<cstring>#define S 0#define T 55555#define inf 0x7fffffffstruct edge{int to,next,v;}e[100001];int n,m,r,c,cnt=1,ans,tot;int head[100001];int h[100001];int q[100001];bool mrk[60][60];inline int min(int a,int b){return a<b?a:b;}inline void ins(int u,int v,int w){e[++cnt].to=v;e[cnt].v=w;e[cnt].next=head[u];head[u]=cnt;}inline void insert(int u,int v,int w){ins(u,v,w);ins(v,u,0);}inline bool bfs(){memset(h,-1,sizeof(h));int t=0,w=1;q[1]=S;h[S]=0;while (t<w){int now=q[++t];for (int i=head[now];i;i=e[i].next) if(h[e[i].to]==-1&&e[i].v) { q[++w]=e[i].to; h[e[i].to]=h[now]+1; }}if (h[T]==-1) return 0;return 1;}inline int dfs(int x,int f){if (x==T||!f) return f;int used=0,w;for (int i=head[x];i;i=e[i].next) if (e[i].v&&h[e[i].to]==h[x]+1) { w=f-used; w=dfs(e[i].to,min(e[i].v,w)); used+=w; e[i].v-=w; e[i^1].v+=w; }if (!used) h[x]=-1;return used;}inline void dinic(){while(bfs())ans+=dfs(S,inf);}int main(){scanf("%d%d%d%d",&n,&m,&r,&c);const int mx[4]={r,c,c,r};const int my[4]={c,r,-r,-c};for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { char ch=getchar(); while (ch!='.'&&ch!='x')ch=getchar(); if (ch=='.'){mrk[i][j]=1;tot++;} }for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (mrk[i][j]) { insert(S,(i-1)*m+j,1); insert((i-1+n)*m+j,T,1); for (int k=0;k<4;k++) { int nx=mx[k]+i; int ny=my[k]+j; if (r==c&&k%2) continue; if (nx>=1&&nx<=n&&ny>=1&&ny<=m&&mrk[nx][ny]) insert((i-1)*m+j,(nx-1+n)*m+ny,1); } }dinic();printf("%d\n",tot-ans);}
- bzoj2150 部落战争
- bzoj2150 部落战争
- BZOJ2150部落战争
- bzoj2150 部落战争
- bzoj2150 部落战争
- bzoj2150: 部落战争
- 【bzoj2150】 部落战争 二分图匹配
- bzoj2150部落战争 最小路径覆盖
- [BZOJ2150]部落战争(二分图匹配)
- 【bzoj2150】部落战争(最小路径覆盖)
- [BZOJ2150]部落战争-二分图匹配
- bzoj2150 部落战争 二分图匹配
- [bzoj2150] 部落战争(二分图最小边覆盖)
- bzoj-2150 部落战争
- BZOJ P2150 部落战争
- 2150: 部落战争
- bzoj2150
- 回顾系列2-部落战争
- windows下Jenkins的搭建
- 着手实现TFIDF算法
- Codeforces Round #256 (Div. 2) A. Rewards(简单题)
- PAT:4-4. 猜数字游戏(15)
- hdu 3635 Dragon Balls ( 并查集路径压缩)
- bzoj2150 部落战争
- POJ 2243
- hdu1241
- KeyboardJS 开发指南 - 与 Three.js 配合使用的捕捉键盘组合键库
- 人工智能自动开发功能
- 自己动手写图片切换代码(jquery)
- MANIFEST.XML文件ACTIVITY的TASK相关属性 ALWAYSRETAINTASKSTATE作用
- PAT:5-0. 求序列前N项和(15)
- ListView