hdu 4104 Discount 01背包变形+优化

来源:互联网 发布:网络拓扑结构选用线缆 编辑:程序博客网 时间:2024/05/21 17:33

题意:就是输入一个商品数n和所有商品的价格,问最小不能组合的价格是多少?

题解:我直接想到的是01背包。。,直接来肯定要TLE的,需要优化下,别人不知道是用什么方法,我自己是用这个接的,就是不知道最坏情况能不能过了。。没计算过

这题中说是01背包变形,其实就是个dp,以已知可以拼凑的价格推出另一个价格,写法跟01背包很想,尤其是两个for。可以理解成将n个体积为价格值,价值为0的物品,放入没有体积限制的背包,问最小不能放满的背包是多少。

我这种写法很简单,只要考虑到几个优化点就OK了:

1.需要从小到大排序,排序后有a[i]<=a[j](i<j),所以如果前i个数不能组合一个小于a[i]的数,那之后也肯定不能组合。

2.前i个商品最大能组合的价格就是他们的价格和。

3.找出处理i个商品后,最小不能组合的商品价格。下次循环就能从这处开始,省下很多时间。


说明:01背包说的是将n个物品有体积和价值,方法哦一个体积V的背包里,求的是最大价值。详解可以搜索背包九讲,一个大神写的。。



耗时:46MS

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <map>#include <string>#include <cmath>using namespace std;const int INF=1e8;const int maxn=1e3+10;const int maxm=1e6+10;int a[maxn];int f[maxm];int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int i,j,k,p,m=0;        for(i=0;i<n;i++)        scanf("%d",&a[i]);        sort(a,a+n);        memset(f,0,sizeof(f));        f[0]=1;        k=0;        for(i=0;i<n;i++)        {            m=m+a[i];//前i个数能组合的最大值。            for(j=m;j>=k;j--)//k是不能组合的最小的一个,这个是很重要的优化,不然就TLE了            {                if(f[j-a[i]])                f[j]=1;            }            while(f[k])k++;            if(k<=a[i])break;//找到最小值如果比a[i]小,那就肯定没办法组合的。        }        while(f[k])k++;        printf("%d\n",k);    }    return 0;}


原创粉丝点击