E

题目大意:切割图形,给你一个非0即1的矩阵,将它切割成多个长方形,使每个小长方形中1的个数不得多于k个,切割的规则,要么切一整行,要么是一整列、

 题解: 二进制枚举。

注意行数最大才是10。用二进制枚举切割某一行,然后在枚举每一列是否需要切割。时间复杂度O(2^h*m)

code:

#include<bits/stdc++.h>
using namespace std;
const int N=1E3+7;
const int INF=1e9+7;
int mp[N][N];
int arr[N];
int n,m,k;
vector<int>ve;
int cal(int x,int y,int j){//用来计算第从x到y行第j列的值。
    int sum=0;
    for(int i=x;i<=y;i++)
        sum+=mp[i][j];
    return sum;
}
int check(){
    int c=ve.size(),sum=0;
    for(int k1=1;k1<c;k1++) arr[k1]=0;
    bool flag=0;
    for(int j=1;j<=m;j++){
        for(int k1=1;k1<c;k1++){
            arr[k1]+=cal(ve[k1-1]+1,ve[k1],j);
            if(arr[k1]>k){
                sum++;
                flag=1;
                break;
            }
        }
        if(!flag) continue ;
        flag=0;
        for(int k1=1;k1<c;k1++){
            arr[k1]=cal(ve[k1-1]+1,ve[k1],j);
            if(arr[k1]>k) return INF;
        }
    }
    return sum;
}
int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            char x;
            cin>>x;
            if(x=='1') mp[i][j]=1;
            else mp[i][j]=0;
        }
    }
    int c=(1<<(n-1))-1;
    int ans=INF;
    for(int i=0;i<=c;i++){
        ve.push_back(0);
        for(int j=0;j<n-1;j++)
            if((1<<j)&i) ve.push_back(j+1);
        ve.push_back(n);
        int x=ve.size();
        ans=min(ans,x-2+check());
        ve.clear();
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Accepting/p/12554854.html