BZOJ 3661: Hungry Rabbit

来源:互联网 发布:baocms7.1完整源码 编辑:程序博客网 时间:2024/06/18 08:21

这道题挺不错的。。反正愚蠢的我没想到这么妙的东西

有种网络流做法 拆拆点搞一搞看看是不是网络流就好 因为bzoj把时限放到了100s 所以就让这种做法过了。。昨天有人还T了 卡了100s 网上面有这里就不写了

在staus有明显的用时分界线。。
我们来说说贪心 为什么我想不到贪心很多年了。。。

不难发现可以用 O(nm) 知道每只兔子在第几天开始能用多少天
这样 在每一天 显然我们尽量用 能用久一点的兔子是更优的

那么在每一天 我们就分别对上一天在用的 以及没在用的分别按能用多少天排个序 在用的从小到大排 没在用的从大到小排
交换前面L个就好了 记得判断一下大小
如果交换之后在用的里面有能用天数=0的 那就无解了
复杂度O(nlognm)

#include<bits/stdc++.h>#define me(a,x) memset(a,x,sizeof a)using namespace std;const int N=805;inline int read(){    int x=0,f=1; char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}    return x*f;}char a[N][N]; int n,m,p,k,c[N][N],r[N];bool Cmp1(int A,int B){return r[A]>r[B];}bool Cmp2(int A,int B){return r[A]<r[B];}int a1[N],a2[N],ans[N][N]; bool in[N];int main(){    int i,j; n=read(),m=read(),k=read(),p=read();    for(i=1;i<=n;++i)scanf("%s",a[i]+1);    for(i=1;i<=n;++i)        for(j=m;j;--j)          if(a[i][j]=='1')c[i][j]=c[i][j+1]+1;          else c[i][j]=0;    int l1=0,l2;    for(i=1;i<=n;++i){        r[i]=c[i][1];        if(c[i][1])a1[++l1]=i;    }    sort(a1+1,a1+1+l1,Cmp1);    l1=k; for(i=1;i<=l1;++i)in[a1[i]]=1,ans[1][i]=a1[i];    bool no=0;    for(j=2;j<=m;j++){        l2=0;        for(i=1;i<=n;i++){            r[i]=c[i][j];            if(c[i][j] && !in[i])a2[++l2]=i;        }        sort(a1+1,a1+1+l1,Cmp2);        sort(a2+1,a2+1+l2,Cmp1);        for(i=1;i<=l1;i++){            if(i>l2 || i>p){                if(r[a1[i]]==0)no=1;                break;            }            if(r[a1[i]]>=r[a2[i]])break;            in[a1[i]]=0; in[a2[i]]=1;            a1[i]=a2[i];        }        for(i=1;i<=k;i++)ans[j][i]=a1[i];        if(no)break;    }    if(no)printf("1\n");    else{        for(i=1;i<=m;++i){            for(j=1;j<=k;++j)printf("%d ",ans[i][j]);            printf("\n");        }    }    return 0;}
1 0
原创粉丝点击