zoukankan      html  css  js  c++  java
  • BZOJ2150部落战争——最小路径覆盖

    题目描述

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

    输入

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

    输出

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

    样例输入

    【样例输入一】
    3 3 1 2
    ...
    .x.
    ...
    【样例输入二】
    5 4 1 1
    ....
    ..x.
    ...x
    ....
    x...

    样例输出

    【样例输出一】
    4
    【样例输出二】
    5
     
    题目给出一个$DAG$求最小路径覆盖。可以在开始将每个点看成一条路径,然后再将路径合并。建模时将每个点拆成出点和入点两个点分别代表这个点的路径的出口和入口,源点连向出点,入点连向汇点,出入点之间不连边。枚举每个非障碍点$u$及它能到达的非障碍点$v$,将$u$的出点连向$v$的入点表示将这两个点的路径合并,然后跑一遍二分图最大匹配即可。答案就是总非障碍点数$-$二分图最大匹配数。
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<bitset>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 0x3f3f3f3f
    #define ll long long
    using namespace std;
    int head[6000];
    int to[60000];
    int next[60000];
    int val[60000];
    int d[6000];
    int q[6000];
    int S,T;
    int n,m;
    int tot=1;
    char s[60][60];
    int x,y;
    int ans;
    void add(int x,int y,int v)
    {
        tot++;
        next[tot]=head[x];
        head[x]=tot;
        to[tot]=y;
        val[tot]=v;
        tot++;
        next[tot]=head[y];
        head[y]=tot;
        to[tot]=x;
        val[tot]=0;
    }
    bool bfs(int S,int T)
    {
        int r=0;
        int l=0;
        memset(q,0,sizeof(q));
        memset(d,-1,sizeof(d));
        q[r++]=S;
        d[S]=0;
        while(l<r)
        { 
            int now=q[l];
            for(int i=head[now];i;i=next[i])
            {
                if(d[to[i]]==-1&&val[i]!=0)
                {
                    d[to[i]]=d[now]+1;
                    q[r++]=to[i];
                }
            }
            l++;
        }
        return d[T]!=-1;
    }
    int dfs(int x,int flow)
    {
        if(x==T)
        {
            return flow;
        }
        int now_flow;
        int used=0;
        for(int i=head[x];i;i=next[i])
        {
            if(d[to[i]]==d[x]+1&&val[i]!=0)
            {
                now_flow=dfs(to[i],min(flow-used,val[i]));
                val[i]-=now_flow;
                val[i^1]+=now_flow;
                used+=now_flow;
                if(now_flow==flow)
                {
                    return flow;
                }
            }
        }
        if(used==0)
        {
            d[x]=-1;
        }
        return used;
    }
    void dinic()
    {
        while(bfs(S,T)==true)
        {
            ans-=dfs(S,0x3f3f3f);
        }
    }
    int find(int x,int y)
    {
    	return (x-1)*m+y;
    }
    int main()
    {
    	scanf("%d%d%d%d",&n,&m,&x,&y);
    	S=n*m*2+1;
    	T=S+1;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%s",s[i]+1);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			if(s[i][j]=='x')
    			{
    				continue;
    			}
    			ans++;
    			add(S,find(i,j),1);
    			add(find(i,j)+n*m,T,1);
    			if(i+x<=n&&j+y<=m&&s[i+x][j+y]=='.')
    			{
    				add(find(i,j),find(i+x,j+y)+n*m,INF);
    			}
    			if(i+y<=n&&j+x<=m&&s[i+y][j+x]=='.')
    			{
    				add(find(i,j),find(i+y,j+x)+n*m,INF);
    			}
    			if(i+x<=n&&j-y>=1&&s[i+x][j-y]=='.')
    			{
    				add(find(i,j),find(i+x,j-y)+n*m,INF);
    			}
    			if(i+y<=n&&j-x>=1&&s[i+y][j-x]=='.')
    			{
    				add(find(i,j),find(i+y,j-x)+n*m,INF);
    			}
    		}
    	}
    	dinic();
    	printf("%d",ans);
    }
  • 相关阅读:
    木有晚餐吃的教训暴力图的时候
    HDU1231最大连续子序列DP
    java连连看(GUI有进度条加背景音乐)
    HDU2064简单hanno塔
    HDU1232并查集入门(畅通工程)
    HDU3460Ancient Printer(trie)
    在window下搭建php+apche+masql的方法(个人的蛋疼经历,绝对可靠)
    Java学生管理系统(GUI)(又写了这种破玩意儿了老师,放过我们吧,能不能来点新意)
    VUE使用elpagination添加分页功能
    JS 中深拷贝的几种实现方法
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/10585096.html
Copyright © 2011-2022 走看看