zoukankan      html  css  js  c++  java
  • 【POJ2226】Muddy Fields

    题目大意:给定一个 N*M 的图,图中有一些格子不能被任何东西覆盖,现有一些宽度为 1,长度任意的骨牌覆盖这些可以被覆盖的格子,骨牌之间可以重叠,求将所有可以被覆盖的格子覆盖所需的最小骨牌数是多少。

    题解:一行连续的可覆盖格子或一列连续的可覆盖格子一定是一起被覆盖的,因此预处理出每一个格子在哪些行/列块中。对于每一个可覆盖的格子来说,这个格子要么被其所属的行块覆盖,要么被其所属的列块覆盖,且必须被覆盖。可知是二分图最小点覆盖的模型,直接匹配即可。

    代码如下

    #include <cstdio>
    #include <utility>
    #include <ctype.h>
    #include <vector>
    #include <memory.h>
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define all(x) x.begin(),x.end()
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    const int dx[]={0,1,0,-1};
    const int dy[]={1,0,-1,0};
    const int mod=1e9+7;
    const int inf=0x3f3f3f3f;
    //const int maxn=
    const double eps=1e-6;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll sqr(ll x){return x*x;}
    inline ll read(){
    	ll x=0,f=1;char ch;
    	do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    	do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    	return f*x;
    }
    /*--------------------------------------------------------*/
    
    int n,m,ans;
    char MP[60][60];
    int blr[60][60],tot1,blc[60][60],tot2;
    vector<int> G[2500];
    bool vis[2500];int match[2500];
    
    void read_and_parse(){
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)scanf("%s",MP[i]+1);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;){
    			if(MP[i][j]=='.'){++j;continue;}
    			++tot1;
    			while(j<=m&&MP[i][j]=='*')blr[i][j]=tot1,++j;
    		}
    	for(int i=1;i<=m;i++)
    		for(int j=1;j<=n;){
    			if(MP[j][i]=='.'){++j;continue;}
    			++tot2;
    			while(j<=n&&MP[j][i]=='*')blc[j][i]=tot2,++j;
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++){
    			if(MP[i][j]=='.')continue;
    			G[blr[i][j]].pb(blc[i][j]);
    		}
    }
    
    bool dfs(int u){
    	for(int i=0;i<G[u].size();i++){
    		int v=G[u][i];if(vis[v])continue;
    		vis[v]=1;
    		if(!match[v]||dfs(match[v])){
    			match[v]=u;return 1;
    		}
    	}
    	return 0;
    }
    
    void solve(){
    	for(int i=1;i<=tot1;i++){
    		memset(vis,0,sizeof(vis));
    		if(dfs(i))++ans;
    	}
    	printf("%d
    ",ans);
    }
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    MYSQL关于数据库的操作命令
    理解js中的原型和原型链
    float引起的高度塌陷问题
    使用webpack2.0 搭建前端项目
    jquery插件开发总结
    js中的OOP编程
    关于gulp的基本使用
    关于requireJs的学习总结
    vuex的学习总结
    事件中的target与currentTarget的区别
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10641913.html
Copyright © 2011-2022 走看看