zoukankan      html  css  js  c++  java
  • BZOJ 1169: [Baltic2008]Grid

    一个矩阵,可以横着切S刀,竖着切R刀,求小矩阵和最大的最小是多少。
    二分答案,dfs出竖着切的,横着贪心check。

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int maxn = 25;
    ll a[maxn][maxn];
    int n,m,R,S;
    
    template<typename T> inline void read(T &x){
    x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
    }
    
    template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
    template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
    template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}
    
    bool ok;
    
    int dl[maxn];
    ll mid;
    ll bs[maxn];
    
    bool isok(){
    	//if(dl[0]==2&&dl[1]==4) cout<<"mid"<<mid<<endl;
    	dl[R]=n;
    	memset(bs,0,sizeof bs);
    	//int bef=0;
    	int cnt=0;
    	for(int i=1;i<=m;i++){
    		bool can=1;
    		for(int j=0;j<=R;j++){
    			if(j==0&&bs[j]+a[dl[j]][i]-a[dl[j]][i-1]>mid) can=0;
    			else if(bs[j]+a[dl[j]][i]-a[dl[j]][i-1]-(a[dl[j-1]][i]-a[dl[j-1]][i-1])>mid)
    				can=0;
    		}
    		if(!can){
    			cnt++;
    			for(int j=0;j<=R;j++){
    				bs[j]=0;
    			}
    		}
    		for(int j=0;j<=R;j++){
    			if(j==0) bs[j]+=a[dl[j]][i]-a[dl[j]][i-1];
    			else bs[j]+=a[dl[j]][i]-a[dl[j]][i-1]-(a[dl[j-1]][i]-a[dl[j-1]][i-1]);
    		}
    		for(int j=0;j<=R;j++)
    			if(bs[j]>mid) return 0;
    	}
    	return cnt<=S;
    }
    
    void dfs(int now,int dep){
    	if(ok) return;
    	if(dep==R){
    		if(isok()) ok=1;
    		return;
    	}
    	for(int i=now;i<n;i++){
    		dl[dep]=i;
    		dfs(i+1,dep+1);
    	}
    }
    
    bool check(ll mid){
    	ok=0;
    	dfs(1,0);
    	if(ok) return 1;
    	return 0;
    }
    
    int main(){
    	//freopen("in.txt","r",stdin);
    	read(n,m,R,S);
    	R=min(R,n-1);S=min(S,m-1);
    	ll l=0,r=0;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			read(a[i][j]),r+=a[i][j];
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
    	//for(int i=1;i<=n;i++)
    	//	for(int j=1;j<=m;j++)
    	//		printf("%d%c",(int)a[i][j]," 
    "[j==m]);
    	ll res=-1;
    	//cout<<check(mid=31)<<endl;
    	//l=r=130;
    	while(l<=r){
    		mid=(l+r)/2;
    		if(check(mid))
    			r=(res=mid)-1;
    		else l=mid+1;
    	}
    	cout<<res;
    	return 0;
    }
    
  • 相关阅读:
    电池的并联与串联
    [转]为什么我会认为SAP是世界上最好用最牛逼的ERP系统,没有之一?
    go module
    thinkPHP5.1自动生成目录结构
    java多线程-锁分析
    Walle 2.0(瓦力)的安装
    轻量日志系统Loki
    Zabbix5.0的安装(超详细)
    政策制定的艺术
    浅谈对golang中的defer,panic,recover理解
  • 原文地址:https://www.cnblogs.com/foreignbill/p/7921148.html
Copyright © 2011-2022 走看看