HDU 2126 Buy the souvenirs (01背包)

题意:我有m元,有n个纪念品,已知它们分别的价格,输出我最多能买多少个不同的纪念品,以及能买到最多不同纪念品时我可选择的方案数。


思路:将m作为容量,纪念品的价格作为消耗,每个纪念品的价值为1(件),容易求得我最多能买的纪念品数。用一个数组s记录方案数,数组kind记录不同纪念品数。


#include 

int main()
{
    #ifdef LOCAL
    freopen("data.in", "r", stdin);
    #endif

    int t, n, mon, price[35], kind[505], s[505], m;
    scanf("%d" ,&t);
    while(t--)
    {
        scanf("\n");
        scanf("%d%d", &n, &mon);
        for(int i = 1; i <= n; i++)
            scanf("%d", &price[i]);

        for(int i = 0; i <= mon; i++)
        {
            kind[i] = 0; s[i] = 1;
        }
        for(int i = 1; i <= n; i++ )
        {
            for(int j = mon; j >= price[i]; j--)
            {
                if(kind[j - price[i]] + 1 >= kind[j])
                {//对于i-th纪念品找到不同纪念品数大于或等于前i-1th的情况
                    if(kind[j - price[i]] + 1 == kind[j])
                    {//不同纪念品数不增加则方案数在原来基础上加
                        s[j] += s[j - price[i]];//这里要注意不是简单的+1
                    }
                    else
                    {//不同纪念品数增加
                        s[j] = s[j - price[i]];
                        kind[j] = kind[j - price[i]] + 1;
                    }
                    //printf("s[%d]=%d\n", j, s[j]);
                }
            }
        }
        if(kind[mon] == 0)printf("Sorry, you can't buy anything.\n");
        else
        {
            printf("You have %d selection(s) to buy with %d kind(s) of souvenirs.\n", s[mon], kind[mon]);
        }
    }


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值