CODEFORCES #632 E. Thief in a Shop (DP的神奇优化)

题目描述:

有$n$种数,每次可以取恰好$k$个数,一种数可以取无数次,问有哪些可能的和。

解题思路:

最朴素的$dp$是$n^4$的,我们考虑优化到$n^3$。因为恰好$k$个数的限制条件有些麻烦,我们将所有数都减去最小的一个数,这样我们可以取少于$k$个,不足的就取最小的那个补充。也就是设$F_{i}$表示减掉最小数后凑到和为$i$至少要$F_{i}$次。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int N = 501;
 7 int n, k, a[N], f[N * N];
 8 
 9 int main() {
10     scanf("%d %d", &n, &k);
11     for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
12     sort(a + 1, a + n + 1);
13     for (int i = 2; i <= n; i ++) a[i] -= a[1];
14     for (int i = 1; i <= k * a[n]; i ++) f[i] = k + 1;
15     for (int i = 2; i <= n; i ++)
16         for (int j = a[i]; j <= k * a[n]; j ++) f[j] = min(f[j], f[j - a[i]] + 1);
17     for (int i = 0; i <= k * a[n]; i ++) if (f[i] <= k) printf("%d ", i + a[1] * k);
18     return 0;
19 }

 

posted @ 2016-08-16 22:02  Awner  阅读(206)  评论(0编辑  收藏  举报