AtCoder Beginner Contest 159 E.Dividing Chocolate
Problem Statement
We have a chocolate bar partitioned into H horizontal rows and W vertical columns of squares.
The square (i,j) at the i-th row from the top and the j-th column from the left is dark if Si,j is 0, and white if Si,j is 1.
We will cut the bar some number of times to divide it into some number of blocks. In each cut, we cut the whole bar by a line running along some boundaries of squares from end to end of the bar.
How many times do we need to cut the bar so that every block after the cuts has
K or less white squares?
Constraints
1≤H≤10
1≤W≤1000
1≤K≤H×W
Si,j is 0 or 1.
Sample Input 1
3 5 4
11100
10001
00111
Sample Output 1
2
Sample Input 2
3 5 8
11100
10001
00111
Sample Output 2
0
Sample Input 3
4 10 4
1110010010
1000101110
0011101001
1101000111
Sample Output 3
3
看到 H H H 的范围应该立马想到暴力,实际上就是暴力,列出横切的所有情况,然后用贪心的思想再竖切就可以了,具体注释看代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
string s[12];
int h,w,k;
cin>>h>>w>>k;
for(int i=0;i<h;i++)
cin>>s[i];
int ans=1e9;
for(int u=0;u<(1<<(h-1));u++){//枚举横向切割的所有情况
int x=__builtin_popcount(u);//横向切割的刀数
int r[x+1]={0};//切x刀后横向看被分成x+1块
int flag=1;//记录每一块是否达标
int cnt=x;//记录此种分法的答案
for(int j=0;j<w;j++){//纵切
int c[x+1]={0};//记录纵切后x+1块所含的1的数量
int p=0;//记数
int mx=0;//记录x+1块中包含1数量最大的那块
for(int i=0;i<h;i++){//记录纵切一刀时x+1块的情况
c[p]+=s[i][j]-'0';
mx=max(mx,c[p]);
if(u&(1<<i)) p++;//如果横向切了一刀标记加加
}
if(mx>k) {flag=0;break;}//如果此时最大块包含的1大于k,那么证明横向切割没有最优,跳到下一组横向切割的情况
mx=0;
for(int i=0;i<=x;i++){//符合条件就横向判断
mx=max(mx,r[i]+c[i]);
}
if(mx>k) {memset(r,0,sizeof(r));cnt++;}//横向的某一块的1的数量大于k就要切一刀
for(int i=0;i<=x;i++) r[i]+=c[i];
}
if(flag) ans=min(ans,cnt);//更新答案
}
cout<<ans;
return 0;
}