• #5:你的背包——6


    自然数拆分,完全背包

     1 #include <cstdio>
     2 #define ll long long
     3 #define mod 2147483648
     4 #define rep(i, a, b) for (int i = a; i <= b; i++)
     5 
     6 int n;
     7 ll f[4005];
     8 
     9 int main() {
    10     scanf("%d", &n);
    11     f[0] = 1;
    12     rep(i, 1, n)
    13         rep(j, i, n)
    14             f[j] = (f[j] + f[j-i]) % mod;
    15     printf("%d", (f[n]-1+mod) % mod);
    16     return 0;
    17 }
    View Code

    POJ1015,自己实现果然要费时调试……按照题面对数据处理一下再背包。打印路径。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <map>
     4 using namespace std;
     5 #define R(a) scanf("%d", &a)
     6 #define rep(i, a, b) for (int i = a; i <= b; i++)
     7 #define irep(i, a, b) for (int i = a; i >= b; i--)
     8 #define init(a, b) memset(a, b, sizeof(a))
     9 
    10 const int maxn = 205;
    11 int n, m, kase;
    12 int a[maxn], b[maxn], t[maxn];
    13 int f[25][850], d[25][850];
    14 map<int, int> pre;
    15 int ans[maxn], p, val1, val2;
    16 
    17 void print(int j, int k, int i) {
    18     ans[++p] = i;
    19     val1 += a[i];
    20     val2 += b[i];
    21     int nxt = pre[i*1000000+j*10000+k];
    22     if (!nxt)    return;
    23     print(j-1, k-t[i], nxt);
    24 }
    25 
    26 int cmp(int a, int b) {
    27     int t = f[m][a], p = f[m][b];
    28     if (t < 0 && p < 0)    return -1;
    29     if (t >= 0 && p >= 0)    return t > p ? a : b;
    30     if (t >= 0)    return a;
    31     return b;
    32 }
    33 
    34 int main() {
    35     while (~scanf("%d%d", &n, &m) && n | m) {
    36         rep(i, 1, n) {
    37             R(a[i]);
    38             R(b[i]);
    39             t[i] = a[i] - b[i] + 20;
    40         }
    41 
    42         init(f, 0xcf);
    43         f[0][0] = 0;
    44         rep(i, 1, n)
    45             irep(j, m, 1)
    46                 rep(k, t[i], 40*m) {
    47                     if (f[j-1][k-t[i]] >= 0 && f[j][k] < f[j-1][k-t[i]] + a[i] + b[i]) {
    48                         f[j][k] = f[j-1][k-t[i]] + a[i] + b[i];
    49                         pre[i*1000000+j*10000+k] = d[j-1][k-t[i]];
    50                         d[j][k] = i;
    51                     }
    52                 }
    53 
    54         rep(i, 0, 20*m) {
    55             int k = cmp(20*m-i, 20*m+i);
    56             if (k >= 0) {
    57                 p = val1 = val2 = 0;
    58                 print(m, k, d[m][k]);
    59                 break;
    60             }
    61         }
    62             
    63         printf("Jury #%d
    Best jury has value %d for prosecution and value %d for defence:
    ", ++kase, val1, val2);    
    64         irep(i, p, 1)    printf(" %d", ans[i]);
    65         puts("
    ");
    66     }
    67     return 0;
    68 }
    View Code

    POJ1742,按多重背包的思路贪心一下。

     1 #include <cstdio>
     2 #include <cstring>
     3 #define maxm 100005
     4 #define init(a, b) memset(a, b, sizeof(a))
     5 #define R(a) scanf("%d", &a)
     6 #define W(a) printf("%d
    ", a)
     7 #define rep(i, a, b) for (int i = a; i <= b; i++)
     8 
     9 int n, m;
    10 int a[101], c[101];
    11 int used[maxm];
    12 bool f[maxm];
    13 
    14 int main() {
    15     while (R(n), R(m), n) {
    16         init(f, 0);
    17         f[0] = true;
    18         rep(i, 1, n)    R(a[i]);
    19         rep(i, 1, n)    R(c[i]);
    20         rep(i, 1, n) {
    21             rep(j, 0, m)    used[j] = 0;
    22             rep(j, a[i], m) {
    23                 if (!f[j] && f[j-a[i]] && used[j-a[i]] < c[i]) {
    24                     f[j] = true;
    25                     used[j] = used[j-a[i]] + 1;
    26                 }
    27             }
    28         }
    29 
    30         int ans = 0;
    31         rep(i, 1, m)    ans += f[i];
    32         W(ans);
    33     }
    34     return 0;
    35 }
    View Code

    BZOJ2287,退背包,可行方案数可以等于总数减去不可行方案数。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define R(a) scanf("%d", &a)
     4 #define rep(i, a, b) for (int i = a; i <= b; i++)
     5 #define irep(i, a, b) for (int i = a; i >= b; i--)
     6 
     7 int n, m;
     8 int w[2005];
     9 int f[2005], g[2005];
    10 
    11 int main() {
    12     R(n), R(m);
    13     f[0] = 1;
    14     rep(i, 1, n) {
    15         R(w[i]);
    16         irep(j, m, 0)
    17             f[j] = (f[j] + f[j-w[i]]) % 10;
    18     }
    19 
    20     rep(i, 1, n) {
    21         rep(j, 0, w[i]-1)    g[j] = f[j];
    22         rep(j, w[i], m)    g[j] = (f[j] - g[j-w[i]] + 10) % 10;
    23         rep(j, 1, m)    printf("%d", g[j]);
    24         puts("");
    25     }
    26     return 0;
    27 }
    View Code

    BZOJ1025,把题目本质抽出来即和为n的拆分,然后难的一点是lcm方案数等价于各素数加和小于等于n的方案数。之后分组背包即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 
     5 int n;
     6 ll f[1001];
     7 int primes[1001], t;
     8 bool mark[1001];
     9 
    10 inline void Get_primes(int n) {
    11     for (int i = 2; i <= n; i++) {
    12         if (!mark[i]) {
    13             primes[++t] = i;
    14         }
    15         for (int j = 1; j <= t && i*primes[j] <= n; j++) {
    16             mark[i*primes[j]] = true;
    17             if (i % primes[j] == 0)    break;
    18         }
    19     }
    20 }
    21 
    22 inline ll dp(int n) {
    23     f[0] = 1ll;
    24     for (int i = 1; i <= t; i++)
    25         for (int j = n; j >= primes[i]; j--)
    26             for (int k = primes[i]; k <= j; k *= primes[i])
    27                 f[j] += f[j-k];
    28     return accumulate(f, f+n+1, 0ll);
    29 }
    30 
    31 int main() {
    32     scanf("%d", &n);
    33     Get_primes(n);
    34     printf("%lld", dp(n));
    35     return 0;
    36 }
    View Code

    BZOJ4247,首先排序,之后才能dp。dp的状态转移不是单纯的01背包因为那样会T,一种写法是处理一下使得大于n的状态都归于n;我用的第二种但私以为网上题解在理解上有些错误。一是这样写以后f[i][j]的定义其实变了,不再是前i个剩j个挂钩而是剩>=j个挂钩;二是选择1个的原因不是只能选1,而是我们本来要取1~n里最大的,而这种写法前面的一定比后面的大所以取1就能保证正确性了。果然最后的输出也不必把f数组遍历一遍,因为0肯定是最大的,直接输出即可AC。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define maxn 2005
     4 #define gc getchar()
     5 #define R(a) a = readint()
     6 #define init(a, b) memset(a, b, sizeof(a))
     7 #define rep(i, a, b) for (int i = a; i <= b; i++)
     8 
     9 const int inf = 0xcfcfcfcf;
    10 int n;
    11 int f[2][maxn];
    12 struct node {
    13     int a, b;
    14     bool operator < (const node x) const {
    15         return a > x.a;
    16     }
    17 }p[maxn];
    18 
    19 inline int readint() {
    20     int x = 0, s = 1, c = gc;
    21     while (c <= 32)    c = gc;
    22     if (c == '-')    s = -1, c = gc;
    23     for (; isdigit(c); c = gc)
    24         x = x * 10 + c - 48;
    25     return x * s;
    26 }
    27 
    28 int main() {
    29     R(n);
    30     rep(i, 1, n) {
    31         R(p[i].a);
    32         R(p[i].b);
    33     }
    34 
    35     sort(p+1, p+1+n);
    36     init(f, 0xcf);
    37     f[0][0] = f[0][1] = 0;
    38     rep(i, 1, n) {
    39         rep(j, 0, n) {        
    40             if (j >= p[i].a) {
    41                 f[i&1][j] = max(f[i-1&1][j], f[i-1&1][j+1-p[i].a] + p[i].b);
    42             } else {
    43                 f[i&1][j] = max(f[i-1&1][j], f[i-1&1][1] + p[i].b);
    44             }
    45         }
    46     }
    47     
    48     printf("%d
    ", f[n&1][0]);
    49     return 0;    
    50 }
    View Code
  • 相关阅读:
    sed command
    【Python3】作用域(局部变量、全局变量)
    【Python3】函数与参数
    【Python3】编程范式
    【Python3】字符解码与编码
    【Python3】文件操作
    【Python3】集合
    【Python3】目录
    【Python3】字典
    【Python3】字符串操作
  • 原文地址:https://www.cnblogs.com/AlphaWA/p/10350413.html
Copyright © 2020-2023  润新知