SGU 116. Index of super-prime 容量背包

4 篇文章 0 订阅

题目链接点这儿

大意就是给出好多物品(测试后得出1000以内的super prime只有201个),每个物品不限个数。让你判断某个容量的背包可不可以正好装满,如果可以装满的话,给出最优的解,就是物品个数最少的解。

很简单的完全背包,不需要二进制压缩,也不用考虑容量。直接写个裸的就可以过。super prime偷懒直接打表了。

第一次wa了,因为没看到最优解。。以为是随便一组解就可以了。

下面放出代码。

#include <bits/stdc++.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)>(b)?(b):(a))
#define rep(i,initial_n,end_n) for(int (i)=(initial_n);(i)<(end_n);i++)
#define repp(i,initial_n,end_n) for(int (i)=(initial_n);(i)<=(end_n);(i)++)
#define reep(i,initial_n,end_n) for((i)=(initial_n);(i)<(end_n);i++)
#define reepp(i,initial_n,end_n) for((i)=(initial_n);(i)<=(end_n);(i)++)
#define eps 1.0e-9
#define MAX_N 1010

using namespace std;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef long long ll;
typedef unsigned long long ull;

int super[220] = { 3, 5, 11, 17, 31, 41, 59, 67, 83, 109, 127, 157, 179, 191, 211, 241, 277, 283, 331, 353, 367, 401, 431, 461, 509, 547, 563, 587, 599, 617, 709, 739, 773, 797, 859, 877, 919, 967, 991, 1031, 1063, 1087, 1153, 1171, 1201, 1217, 1297, 1409, 1433, 1447, 1471, 1499, 1523, 1597, 1621, 1669, 1723, 1741, 1787, 1823, 1847, 1913, 2027, 2063, 2081, 2099, 2221, 2269, 2341, 2351, 2381, 2417, 2477, 2549, 2609, 2647, 2683, 2719, 2749, 2803, 2897, 2909, 3001, 3019, 3067, 3109, 3169, 3229, 3259, 3299, 3319, 3407, 3469, 3517, 3559, 3593, 3637, 3733, 3761, 3911, 3943, 4027, 4091, 4133, 4153, 4217, 4273, 4339, 4397, 4421, 4463, 4517, 4549, 4567, 4663, 4759, 4787, 4801, 4877, 4933, 4943, 5021, 5059, 5107, 5189, 5281, 5381, 5441, 5503, 5557, 5623, 5651, 5701, 5749, 5801, 5851, 5869, 6037, 6113, 6217, 6229, 6311, 6323, 6353, 6361, 6469, 6599, 6653, 6661, 6691, 6823, 6841, 6863, 6899, 7057, 7109, 7193, 7283, 7351, 7417, 7481, 7523, 7607, 7649, 7699, 7753, 7841, 7883, 8011, 8059, 8101, 8117, 8221, 8233, 8287, 8377, 8389, 8513, 8527, 8581, 8719, 8747, 8761, 8807, 8849, 8923, 8999, 9041, 9103, 9293, 9319, 9403, 9461, 9539, 9619, 9661, 9739, 9833, 9859, 9923, 9973 };

int pre[10010], dp[10010];

int main() {
    int n;
    scanf("%d", &n);
    fill(dp, dp + n + 1, INT_MAX);
    dp[0] = 0, pre[0] = -1;
    repp(i, 0, n) {
        for(int j = 0; j < 201 && i+super[j] <= n; j++) {
            if(dp[i] < INT_MAX && dp[i+super[j]] > dp[i] + 1) {
                dp[i+super[j]] = dp[i] + 1;
                pre[i+super[j]] = i;
            }
        }
    }
    if(dp[n] != INT_MAX) {
        printf("%d\n", dp[n]);
        while(n) {
            printf("%d ", n - pre[n]);
            n = pre[n];
        }
    }
    else puts("0");
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值