zoukankan      html  css  js  c++  java
  • Bookshelf 2(poj3628,01背包,dp递推)

    题目链接:Bookshelf 2(点击进入)

    题目解读:

    给n头牛,给出每个牛的高度h[i],给出一个书架的高度b(所有牛的高度相加>书架高度b),现在把一些牛叠起来(每头牛只能用一次,但不同的牛可能身高相同),在这些叠起来的牛的总高度>书架b的基础上,找出最小的差距(由于输入的数据会保证所有牛的高度相加>书架高度b,所以差距不为负)

    还是看不懂题目?

    举个栗子:

    现在有五头牛高度分别为3 1 3 5 6,书架高度b=16,我们可以把五头牛都叠起来,总高度为18,差距为18-16=2,但这样差距不是最小的,最小的差距是:(3+3+5+6)-16=1

    这题可以看成01背包是每个牛只能选一次或者不选,然后我们可以先忽略书架高度b,对于单个牛高度h[i],我们可以看成 价值[i]=占用空间[i]=h[i],因为牛的占用空间就是高度也就是他的价值,毕竟最后需要总高度>b,那这不就是总价值>b

    我在写的时候卡在如何处理最小差距,原来最后是这样的:如果我们按平常01去运算,最后会得到一个f[]数组里面塞满了数据,并且从左到右是不降低的,f[j]的意义就是容量为j时的最大总高度,那么j是从1~sum(所有牛高度和)的,比如说书架高度为b=15,当f[j]的值<b,那么如果f[j+1]的值>=b了,则f[j+1]-b就是我们要的高度,因为f[j]到f[j+1]的空间最大容量只加了1,而牛的高度最起码>=1吧

    这题在普通的01背包基础上,还在最后加入了选择数据的过程

    因为数组f[]从左到右是恒不降低的,那么直接从左到右找出第一个>=b的f[j]就是最小差距了

    下面的代码涉及滚动数组与01背包空间优化,如果不了解建议先看我的另一篇:对01背包的分析与理解(图文)

    下面上代码

    #include<cstdio>
    #include<iostream>
    #include<string.h>
    #define ll long long
    using namespace std;
    ll h[25];//存放每个牛的高度
    int main()
    {
        ll n,b,sum=0;
        cin>>n>>b;
        for(ll i=1;i<=n;i++)
        {
            scanf("%lld",&h[i]);
            sum+=h[i];//sum为所有奶牛高度和
        }
        ll f[sum+10];
        memset(f,0,sizeof(f));//清空数组
        for(ll i=1;i<=n;i++)
            for(ll j=sum;j>=h[i];j--)
            {
                f[j]=max(f[j],f[j-h[i]]+h[i]);//看作价值=占用空间=高度
            }
        for(ll i=1;i<=sum;i++)
            if(f[i]>=b)//如果差距>=0
            {
                cout<<f[i]-b<<endl;
                return 0;
            }
    
    }
    点击加号查看代码
  • 相关阅读:
    我再也不相信正解了……
    悬线法
    防线 Defence
    奶牛浴场
    环状两段最大子段和
    三步必杀
    加工生产调度
    种树
    UVA11134 传说中的车 Fabled Rooks
    UVA 11054 Gergovia的酒交易 Wine trading in Gergovia
  • 原文地址:https://www.cnblogs.com/zyacmer/p/9970251.html
Copyright © 2011-2022 走看看