P1021 邮票面值设计

P1021 邮票面值设计

学到了,搜索+dp剪枝

思路确实很清晰,搜出\(K\)种邮票,拼邮票时也是完全背包,按NOIP2018D1T2那样去做,再维护下最大值就是了。

但是问题就在于搜索部分太浪费时间了,我们考虑剪枝。

  1. 搜邮票的时候记录前面张邮票的面值,从前面面值+1开始搜。
  2. 当我们已经搜出了一部分邮票时,dp一下看看当前的\(MAX\)我们搜下张牌面值的上界就是\(MAX+1\)。因为太大了没办法连续。

这样就能过了。第二个剪枝学到了。。。

代码:

#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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值