学到了,搜索+dp剪枝
思路确实很清晰,搜出\(K\)种邮票,拼邮票时也是完全背包,按NOIP2018D1T2那样去做,再维护下最大值就是了。
但是问题就在于搜索部分太浪费时间了,我们考虑剪枝。
这样就能过了。第二个剪枝学到了。。。
代码:
#include<bits/stdc++.h>
using std::cin;
using std::cout;
using std::endl;
const int maxn = 16;
int n, k;
int a[maxn];
int dp[100005];
int answer[maxn];
int ans;
int check() {
memset(dp, 0x3f, sizeof dp);
dp[0] = 0;
for(int i = 1; ; i++) {
for(int j = 1; j <= k; j++) {
if(i - a[j] >= 0 && dp[i - a[j]] < n) {
dp[i] = std::min(dp[i], dp[i - a[j]] + 1);
}
}
if(dp[i] == 0x3f3f3f3f) {
return i - 1;
}
}
}
void dfs(int t, int mx) {
if(t == k + 1) {
if(mx > ans) {
ans = mx;
for(int i = 1; i <= k; i++) answer[i] = a[i];
}
} else {
for(int i = a[t - 1] + 1; i <= mx + 1; i++) {
a[t] = i;
dfs(t + 1, check());
a[t] = 0;
}
}
}
int main() {
cin >> n >> k;
dfs(1, 0);
for(int i = 1; i <= k; i++) cout << answer[i] << ' ';
cout << endl;
cout << "MAX=" << ans << endl;
return 0;
}
原文:https://www.cnblogs.com/Garen-Wang/p/11273328.html