【第22期】观点:IT 行业加班,到底有没有价值?

BZOJ【1082】栅栏

原创 2016年08月29日 15:50:24

1082: [SCOI2005]栅栏

Time Limit: 10 Sec Memory Limit: 162 MB
Description

农夫约翰打算建立一个栅栏将他的牧场给围起来,因此他需要一些特定规格的木材。于是农夫约翰到木材店购
买木材。可是木材店老板说他这里只剩下少部分大规格的木板了。不过约翰可以购买这些木板,然后切割成他所需
要的规格。而且约翰有一把神奇的锯子,用它来锯木板,不会产生任何损失,也就是说长度为10的木板可以切成长
度为8和2的两个木板。你的任务:给你约翰所需要的木板的规格,还有木材店老板能够给出的木材的规格,求约翰
最多能够得到多少他所需要的木板。

Input

第一行为整数m(m<= 50)表示木材店老板可以提供多少块木材给约翰。紧跟着m行为老板提供的每一块木板的长
度。接下来一行(即第m+2行)为整数n(n <= 1000),表示约翰需要多少木材。接下来n行表示他所需要的每一块木板
的长度。木材的规格小于32767。(对于店老板提供的和约翰需要的每块木板,你只能使用一次)。

Output

只有一行,为约翰最多能够得到的符合条件的木板的个数。

Sample Input

4
30
40
50
25
10
15
16
17
18
19
20
21
25
24
30

Sample Output

7

这道题可以用搜索加2分来做。。。
代码最主要的优化就是:如果浪费的木材+需要的材料比总值还要多,就是最小的木块都比它大,那么他当前就已经分不出任何木块了。
不懂的就看我的代码注释咯!!WAW

#include<cstdio>     
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<set>
#include<map>
#include<sstream>
#include<iostream>
#include<algorithm>
//一堆猥琐头文件 
using namespace std;
int a[110],b[1100],s[1100];
int n,m,ans,mid,kk;
int cmp(const void *xx,const void *yy)    //CMP,不要告诉我你不会 
{
    int n1=*(int *)xx;
    int n2=*(int *)yy;
    if(n1>n2) return 1;
    if(n1<n2) return -1;
    return 0;
}
bool dfs(int k,int now)
{
    if(k==0) return true;     //如果k=0就说明这个木头可以得到 
    if(s[mid]+kk>ans) return false;   //如果这个木头加上那些零碎的木头比老板的总和大的话,就得不到这块木头 
    bool bk;
    for(int i=now;i<=m;i++)   //从老板剩下的木头开始for 
    {
        if(a[i]>=b[k])    //如果老板这块木头可以切出b[k]这块木头 
        {
            a[i]-=b[k];   //就切掉b[k]这块木头 
            if(a[i]<b[1]) kk+=a[i];   //如果老板的木头比约翰最小的一块小,就累加 
            if(b[k-1]==b[k]) bk=dfs(k-1,i);  //如果前一块木头和现在的规格一样,就从now询问b[k-1] 
            else bk=dfs(k-1,1);  //否则就从1开始询问b[k-1] 
            if(a[i]<b[1]) kk-=a[i];    //如果现在这块木头还比最小的小,就从总和中减去它 
            a[i]+=b[k];     //老板的木头就加回b[k]的规格 
            if(bk==true) return true;   //这块木头可以获得 
        }
    }
    return false;   //这块木头不能获得 
}
int main()
{
//  freopen("fency.in","r",stdin);     这是本机测试的语句 
//  freopen("fency.out","w",stdout);
    ans=0;
    scanf("%d",&m);
    for(int i=1;i<=m;i++)          //先将老板所有木头的规格相加 
    {
        scanf("%d",&a[i]);
        ans+=a[i];
    }
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    qsort(a+1,m,sizeof(int),cmp);      //快排 
    qsort(b+1,n,sizeof(int),cmp);
    s[0]=0; for(int i=1;i<=n;i++) s[i]=s[i-1]+b[i];     //计算约翰木头尺寸的和 
    while(s[n]>ans) n--;     //如果约翰木头尺寸和最大的大于老板所有木头的尺寸和,就将这个值删除 
    int l=1,r=n,answer=0;              
    kk=0;
    while(l<=r)       //二分查找 
    {
        mid=(l+r)/2;
        if(dfs(mid,1)) 
        {
            l=mid+1; answer=mid;    //记录结果 
        }
        else r=mid-1;
    } 
    printf("%d\n",answer);
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

bzoj1082: [SCOI2005]栅栏

传送门 二分答案。 显然切最小的几块最优。 暴力枚举当前是从什么地方切出来的。 但是显然要TLE 于是乎我们可以召唤王**了。 王**の剪枝: 1.当前剩余木材大小小于最小需要木材就丢弃...

内存屏障(内存栅栏)

内存栅栏是这么一种技术:让一个CPU处理单元中的内存状态对其他的CPU处理单元可见。 在底层内存栅栏是一组指令,一般包括Store Barrier、Load Barrier和Full Barrier。 不同的CPU架构有不同的实现方式,以X86为例:Store Barrier,强制所有在store屏障指令之前的store指令,都在该store屏障指令执行之前被执行,并把store缓冲区的数据都刷到主存 Load Barrier,强制所有在load屏障指令之后的load指令,都在该load屏障指令执行之后被执行,并且一直等到load缓冲区被该CPU读完才能执行之后的load指令

bzoj1082: [SCOI2005]栅栏

这道题一看就是暴搜啊。。 但是暴搜明显会超时啊。。 所以想了想加了个二分。。 发现二分还是过不了啊。。 又是经过了大神的指导。。 发现有一个玄学剪枝啊。。 不想加详细的解释啊啊。。 自己...

HDOJ 1079 && POJ 1082 Calendar Game (博弈: 暴力枚举所有状态的P\N)

//1079 Calendar Game 博弈 暴力枚举所有状态的P\N,其实网上有非常简单的做法 #include&lt;iostream&gt; #include&lt;stdio.h&gt; #include&lt;string.h&gt; #include&lt;stdlib.h&gt; #include&lt;stack&gt; using namespace std; bool vis[105][15][35]; int mon[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};

[BZOJ1082][SCOI2005]栅栏

[BZOJ1082][SCOI2005]栅栏
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)