Galaxy OJ 六校联测4 T4:切蛋糕(二分答案)

来源:互联网 发布:类似prezi的软件 编辑:程序博客网 时间:2024/05/01 17:39

Galaxy OJ 六校联测4 T4:切蛋糕



题目分析:

要使得最小值尽可能的大,切某一刀难以保证其最优解,但是任何时候都不要忘记一种方法——二分答案.
若此题用二分答案的方法来做就迎刃而解了

要使得答案尽可能是合法解,采用贪心思想,
sum[i][j]表示(1,1)~(i,j)的和,那么则有
当sum[i][M]-sum[pre][M]>=ans*B时,就有可能成立
对于每一行(也就是横切两刀形成的大行)切成小蛋糕也类似,
(sum[i][j]-sum[pre][j])-(sum[i][last]-sum[pre][last])>=ans

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=500+10;int read(){    char ch=getchar();int ret=0,flag=1;    while(ch<'0'||ch>'9') {if(ch=='-') flag=-1; ch=getchar();}    while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();    return ret*flag;}int N,M,A,B;int sum[maxn][maxn];//二维前缀和bool check(int ans){    int cnta=0,pre=0;//cnta表示已经完成的行数,pre表示上一次横切的位置    for(int i=1;i<=N;i++) if(sum[i][M]-sum[pre][M]>=B*ans) {        int cntb=0,last=0;//cntb表示该行完成的小蛋糕个数,last表示上一次竖切的位置        for(int j=1;j<=M;j++) if((sum[i][j]-sum[pre][j])-(sum[i][last]-sum[pre][last])>=ans) last=j,cntb++;        if(cntb>=B) pre=i,cnta++;    }    return cnta>=A;}int work(int l,int r)//二分答案{    int ans=0;    while(l<=r) {        int mid=(l+r)>>1;        if(check(mid)) ans=mid,l=mid+1;        else r=mid-1;    }    return ans;}int main(){    N=read(),M=read(),A=read(),B=read();    for(int i=1;i<=N;i++)        for(int j=1;j<=M;j++) {            sum[i][j]=read();            sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];        }    int ans=work(0,sum[N][M]);    printf("%d",ans);    return 0;}
0 0
原创粉丝点击