AtCoder Beginner Contest 159 E.Dividing Chocolate

25 篇文章 0 订阅
20 篇文章 1 订阅

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旺 崽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值