zoukankan      html  css  js  c++  java
  • P3231 [HNOI2013]消毒

    P3231 [HNOI2013]消毒

    二维覆盖我们已经很熟悉了

    扩展到三维,枚举其中较小的一维,这里定义为$a$

    以$a$为关键字状压,$1$表示该面全选

    剩下的面和二维覆盖一样二分图匹配

    如果还没接触过二维覆盖,简要地说一下

    代价是$min(x,y)$,假设$x$比$y$小,全染相当于染$x$次$1×y$的区域,故全染不如一条一条染

    My complete code: 

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const LL inf=0x3f3f3f3f;
    const LL maxn=6000;
    inline LL Read(){
    	LL x=0,f=1; char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-') f=-1; c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		x=x*10+c-'0'; c=getchar();
    	}return x*f;
    }
    struct node{
    	LL to,next;
    }dis[6000000];
    LL a,b,c,T,num,cnt,ans,minn,up;
    LL head[maxn],visit[maxn],mat[maxn],que[4][maxn];
    bool piece[maxn];
    inline void Add(LL u,LL v){
    	dis[++num]=(node){v,head[u]}; head[u]=num;
    }
    bool Dfs(LL u,LL val){
    	for(LL i=head[u];i;i=dis[i].next){
    		LL v=dis[i].to;
    		if(visit[v]!=val){
    			visit[v]=val;
    			if(!mat[v]){
    				mat[v]=u;
    				return true;
    			}else if(Dfs(mat[v],val)){
    				mat[v]=u;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    inline void Solve(LL bit){
    	LL sum=0;
    	for(LL i=1;i<=a;++i)
    	    if((bit>>(i-1))&1){
    	        piece[i]=false,
    	        ++sum;
    	    }else
    	        piece[i]=true;
    	num=0;
    	for(LL i=1;i<=b;++i)
    	    head[i]=0;
    	for(LL i=1;i<=cnt;++i)
    	    if(piece[que[1][i]])
    	        Add(que[2][i],que[3][i]);
    	for(LL i=1;i<=c;++i)
    	    mat[i]=0,
    		visit[i]=0;
    	for(LL i=1;i<=b;++i)
    		if(Dfs(i,i))
    		    ++sum;
    	ans=min(ans,sum);
    }
    int main(){
    	T=Read();
    	while(T--){
    		cnt=0;
    		a=Read(),b=Read(),c=Read();
    		for(LL i=1;i<=a;++i)
    		    for(LL j=1;j<=b;++j)
    		        for(LL k=1;k<=c;++k)
    		            if(Read()){
    		            	que[1][++cnt]=i,
    		            	que[2][cnt]=j,
    		            	que[3][cnt]=k;
    					}
    		minn=min(a,min(b,c));
    		if(minn==b){
    			swap(a,b);
    			swap(que[1],que[2]);
    		}else if(minn==c){
    			swap(a,c);
    			swap(que[1],que[3]);
    		}
    		up=(1<<a); ans=inf;
    		for(LL i=0;i<up;++i)
    		    Solve(i);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Web前端基础(1):HTML(一)
    python基础(35):协程
    python基础(34):线程(二)
    python基础(33):线程(一)
    python基础(32):进程(二)
    python基础(31):进程(一)
    python基础(30):黏包、socket的其他方法
    用keychain这个特点来保存设备唯一标识。
    判断iPhone的WiFi是否打开的两种方法 之是否连接上 WiFi
    NSStringCompareOptions
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10123612.html
Copyright © 2011-2022 走看看