USACO Brownie Slicing

USACO Brownie Slicing

洛谷传送门

JDOJ传送门

Description

Bessie has baked a rectangular brownie that can be thought of as
an RxC grid (1 <= R <= 500; 1 <= C <= 500) of little brownie squares.
The square at row i, column j contains N_ij (0 <= N_ij <= 4,000)
chocolate chips.

Bessie wants to partition the brownie up into AB chunks (1 <= A
<= R; 1 <= B <= C): one for each of the A
B cows. The brownie is
cut by first making A-1 horizontal cuts (always along integer
coordinates) to divide the brownie into A strips. Then cut each
strip independently with B-1 vertical cuts, also on integer
boundaries. The other A*B-1 cows then each choose a brownie piece,
leaving the last chunk for Bessie. Being greedy, they leave Bessie
the brownie that has the least number of chocolate chips on it.

Determine the maximum number of chocolate chips Bessie can receive,
assuming she cuts the brownies optimally.

As an example, consider a 5 row x 4 column brownie with chips
distributed like this:

         1 2 2 1
         3 1 1 1
         2 0 1 3
         1 1 1 1
         1 1 1 1

Bessie must partition the brownie into 4 horizontal strips, each
with two pieces. Bessie can cut the brownie like this:

       1 2 | 2 1
       ---------
       3 | 1 1 1
       ---------
       2 0 1 | 3
       ---------
       1 1 | 1 1
       1 1 | 1 1

Thus, when the other greedy cows take their brownie piece, Bessie
still gets 3 chocolate chips.

Input

* Line 1: Four space-separated integers: R, C, A, and B

* Lines 2..R+1: Line i+1 contains C space-separated integers: N_i1,
..., N_iC

Output

* Line 1: A single integer: the maximum number of chocolate chips that
Bessie guarantee on her brownie

Sample Input

5 4 4 2 1 2 2 1 3 1 1 1 2 0 1 3 1 1 1 1 1 1 1 1

Sample Output

3


题解:

看到最小值最大,果断二分。重点是如何判断当前二分的合不合法。

抓住二分的本质:二分的是答案,答案是什么?最小值最大。如何判断合不合法?就看能不能割出这个值,能割出来,说明不够大。割不出来,说明太大了,需要减小。

最后就维护一个矩阵前缀和来优化枚举即可。

代码:

#include<cstdio>
using namespace std;
int n,m,a,b,map[510][510],s[510][510],ans;
bool check(int x)
{
    int now=0,num=0;
    for(int i=1;i<=n;i++)
    {
        int dis=0,sum=0;
        for(int j=1;j<=m;j++)
            if(dis+(s[i][j]-s[i][j-1])-(s[now][j]-s[now][j-1])<x)
                dis+=(s[i][j]-s[i][j-1])-(s[now][j]-s[now][j-1]);
            else
            {
                sum++;
                dis=0;
            }
        if(sum>=b)
            now=i,num++;
    }
    if(num<a) 
		return 0;
    return 1; 
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&a,&b);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&map[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            s[i][j]=s[i-1][j]+s[i][j-1]+map[i][j]-s[i-1][j-1];
    int l=0,r=s[n][m];
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))
        {
            l=mid+1;
            ans=mid;
        }
        else 
			r=mid-1;
    }
    printf("%d",ans);
	return 0;
}
posted @ 2020-10-27 09:29  Seaway-Fu  阅读(82)  评论(0编辑  收藏  举报