hdu 4104 Discount 01背包变形+优化

题意:就是输入一个商品数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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值