USACO Section 4.1 Fence Rails

来源:互联网 发布:mac 邮件储存位置 编辑:程序博客网 时间:2024/05/30 19:34

题意:

n个木头  m个木块  问: 任意的切木头  最多能得到多少个想要的木块


思路:

搜索+剪枝  这题剪枝很巧妙

首先  只要切好的木块尽量多就好  所以切小的木块一定合适  因此木块要排序

然后  木块有序了  答案自然单调了  因此答案可以二分

在后  考虑数据大小  有1000+的木块  不过木块的大小只有100+  即  有好多木块同样大  那么  相同大小的木块要避免搜索重复情况 (即  木块1由木头1切出,木块2由木头2切出  和  木块1由木头2切出,木块2由木头1切出)

最后  最关键的一点!  搜索的时候记录浪费的木头大小  什么叫浪费?  就是这块木头再也切不出东西了就浪费了  如果浪费的大小比 木头总和 减去 当前二分的答案所对应的木块总和 要大那么一定无解!!(不加这个TLE  加了就0秒过…)


代码:

/*ID: housera1PROG: fence8LANG: C++*/#include<cstdio>#include<cstring>#include<algorithm>#include<ctime>#include<cstdlib>using namespace std;#define M 1050int n,m,ans,dum,mid,space;int x[M],f[M],sum[M];bool ok(int floor,int num){    if(!floor) return true;    if(space>dum-sum[mid]) return false; //非常重要    int i,loc;    for(i=num;i<=n;i++)    {        if(x[i]>=f[floor])        {            x[i]-=f[floor];            if(x[i]<f[1]) space+=x[i];            if(f[floor-1]==f[floor]) loc=i; //非常重要            else loc=1;            if(ok(floor-1,loc))            {                x[i]+=f[floor];                return true;            }            if(x[i]<f[1]) space-=x[i];            x[i]+=f[floor];        }    }    return false;}void solve(){    int l=0,r=m;    while(l<=r) //能优化很多  不过应该可有可无    {        mid=(l+r)>>1;        space=0;        if(dum>=sum[mid]&&ok(mid,1))        {            ans=mid;            l=mid+1;        }        else r=mid-1;    }}bool cmp(int fa,int fb){    return fa>fb;}int main(){int Debug=0;if(!Debug){freopen("fence8.in","r",stdin);freopen("fence8.out","w",stdout);}int i;    scanf("%d",&n);    for(i=1;i<=n;i++)    {        scanf("%d",&x[i]);        dum+=x[i];    }    sort(x+1,x+n+1,cmp);//无所谓的剪枝    scanf("%d",&m);    for(i=1;i<=m;i++) scanf("%d",&f[i]);    sort(f+1,f+m+1); //非常重要    for(i=1;i<=m;i++) sum[i]=sum[i-1]+f[i];    while(sum[m]>dum) m--; //无所谓的剪枝    solve();    printf("%d\n",ans);return 0;}


0 0
原创粉丝点击