(Educational Codeforces Round 9)Thief in a Shop(dp)

本文介绍了一个经典的背包问题求解方法,通过使用动态规划算法解决如何从n种物品中选取k件,使得总价值覆盖所有可能的组合。文章提供了一段C++代码实现,并详细解释了算法思路。

Thief in a Shop

time limit per test5 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
A thief made his way to a shop.

As usual he has his lucky knapsack with him. The knapsack can contain k objects. There are n kinds of products in the shop and an infinite number of products of each kind. The cost of one product of kind i is ai.
The thief is greedy, so he will take exactly k products (it’s possible for some kinds to take several products of that kind).
Find all the possible total costs of products the thief can nick into his knapsack.

Input

The first line contains two integers n and k (1 ≤ n, k ≤ 1000) — the number of kinds of products and the number of products the thief will take.

The second line contains n integers ai (1 ≤ ai ≤ 1000) — the costs of products for kinds from 1 to n.

Output

Print the only line with all the possible total costs of stolen products, separated by a space. The numbers should be printed in the ascending order.

Examples

input

3 2
1 2 3

output

2 3 4 5 6

input

5 5
1 1 1 1 1

output

5

input

3 3
3 5 11

output

9 11 13 15 17 19 21 25 27 33


题意
有n个数,然后这n个数里面选k个加起来
问你一共能加出来多少种

题解:
多项式加法,加k次,问你最后的数是哪些。
DP。dp[i]表示最少用多少个非a[1]能够构成a[1]*k+i的。


#include<bits/stdc++.h>
using namespace std;

int a[1010], dp[1000005], done[1010]={0};

int main()
{
    int mod = 1e9;
    fill( dp + 1, dp + 1000001 , mod);
    int n ,k, mn = mod, mx = 0;
    cin >> n >> k;
    for(int i=1;i<=n;++i)
    {
        cin >> a[i];
        mn = min( mn , a[i]);
        mx = max( mx , a[i]);
    }
    for(int i=1;i<=n;++i)
        a[i] -= mn;

    int t = 0;
    for(int i=1;i<=n;++i)
        if( a[i] != 0)
            a[++t] = a[i];          

    n = t;
    dp[0]=0;
    for(int i = 1; i <= n;++i){
        if( done[a[i]])
            continue;
        done[a[i]] = 1;
        for(int j = 1; j<=mx*k;++j){
            if(j>=a[i])
                if(dp[j] > dp[j-a[i]] + 1)
                    dp[j] = dp[j-a[i]] + 1;
        }
    }


    for(int i = 0; i <= mx * k; ++i)
        if( dp[i] <= k)
            printf("%d ",mn * k + i);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值