【Henu ACM Round #12 E】Thief in a Shop

【链接】 我是链接,点我呀:)
【题意】

n个物品,每个物品都有无限个。

第i个物品的价格是一样都,都是ai

让你从中选出恰好k个物品

问你选出的物品的总价值 有多少种不同的可能。

【题解】

可以用f[j]表示物品的总价值为j最少需要选多少个物品。 for (int i = 1;i <= n;i++) for (int j = a[i];j <= k*a[i];j++){ f[j] = min(f[j],f[j-a[i]]+1); } 然后对于价值j; 如果f[j]==k的话。j就可行? 但是如果f[j]这个时候。我们可以这样,先把所有的a[i]都减去min{a[i]}
然后再按照相同的方法求出f[i]数组。
这个时候,如果f[j]<=k的话,那么j+imin{a[i]}就一定是可以凑出来的。
因为如果不足k个的话,就用k个min{a[i]}分别加到每一个数字上(没有的数字视为0)
这样就凑成了数字j+i
min{a[i]};
且反过来想。如果j是用原数组中的数字可以凑成的。
那么我们在做的时候,显然j-k*i就会被认为是可以凑成的了。

然后显然也不会说造成多解,误解的情况。因此算法成立。
类似的一道题:我是链接,点我呀:)

【代码】

/*
  	1.Shoud it use long long ?
  	2.Have you ever test several sample(at least therr) yourself?
  	3.Can you promise that the solution is right? At least,the main ideal
  	4.use the puts("") or putchar() or printf and such things?
  	5.init the used array or any value?
  	6.use error MAX_VALUE?
  	7.use scanf instead of cin/cout?
  	8.whatch out the detail input require
*/
/*
    一定在这里写完思路再敲代码!!!
*/
#include <bits/stdc++.h>
using namespace std;

const int N = 1e3;

int n,k;
int a[N+10],f[N*N+10];

int main(){
	#ifdef LOCAL_DEFINE
	    freopen("rush_in.txt", "r", stdin);
	#endif
	ios::sync_with_stdio(0),cin.tie(0);
    cin >> n >> k;
    for (int i = 1;i <= n;i++) cin >> a[i];
    sort(a+1,a+1+n);
    n = unique(a+1,a+1+n) - a - 1;
    for (int i = 2;i <= n;i++) a[i]-=a[1];

    f[0] = 0;
    for (int i = 1;i <= N*N;i++) f[i] = k+1;
    for (int i = 2;i <= n;i++)
        for (int j = a[i];j <= k*a[i];j++)
            f[j] = min(f[j],f[j-a[i]]+1);

    for (int i = 0;i <=N*N;i++)
        if (f[i]<=k){
            cout <<i+k*a[1]<<' ';
        }
	return 0;
}

posted @ 2018-01-26 21:43  AWCXV  阅读(146)  评论(0编辑  收藏  举报