邮票 Stamps
思路
设\(f[i][j]\)为考虑前\(i\)个数,当面值为\(j\)时的最小邮票数,则状态转移式如下(完全背包计数):
\(f[i][j] = min(f[i - 1][j], f[i][j - coins[i]] + 1)\), 初始化\(f = inf, f[x][0] = 0\)。
那么我们便可以得到考虑前\(n\)个数,区间\([1, maxN]\) (考虑数据范围\(max(k) \times max(a_i) = 2e6\)), 的最小所需邮票数,通过枚举便可以得到答案。
复杂度\(O(n \times 2e6) \le 2e7\)
思路
#include <bits/stdc++.h>
#include <cstring>
#define rep(i, j, k) for(i64 i = j; i <= k; i ++)
#define per(i, j, k) for(int i = j; i >= k; i --)
using i64 = long long;
/*
完全背包
dp[i][j] = max(dp[i - 1][j], dp[i][j - v[i]] + w[i]);
*/
const int N = 3e3 + 5, MAX = 2e6 + 10;
i64 dp[MAX], v[N];
int main() {
int n, m;
std::cin >> m >> n;
rep(i, 1, n) {
std::cin >> v[i];
}
memset(dp, 0x3f, sizeof dp);
dp[0] = 0;
rep(i, 1, n) {
rep(j, v[i], MAX) {
dp[j] = std::min(dp[j], dp[j - v[i]] + 1);
// if(dp[j] > m) {
// break;
// }
}
}
int ans = 0;
for(int i = 1; i <= MAX; i ++) {
if(dp[i] > m) {
break;
}
ans ++;
}
std::cout << ans;
}