为了能到远方,脚下的每一步都不能少.|

Zac-saodiseng

园龄:2年4个月粉丝:3关注:0

ACM预备队-week8(DP2)

1.疯狂的采药

完全背包

题目链接:P1616 疯狂的采药 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 const int N=10010;
 5 const int M=1e7+5;
 6 int T,m;
 7 int t[N],w[N],f[M];
 8 signed main()
 9 {
10     cin>>T>>m;
11     for(int i=1;i<=m;i++)cin>>t[i]>>w[i];//读入m个物品的体积和权重
12     
13     for(int i=1;i<=m;i++)
14         for(int j=t[i];j<=T;j++)
15             f[j]=max(f[j],f[j-t[i]]+w[i]);
16             
17     cout<<f[T];
18     return 0;
19 }
复制代码

2.樱花

题目链接:P1833 樱花 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

多重背包二进制优化

复制代码
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int mod=100007;
 4 long long DP[10086110];
 5 long long w[10086110],v[10086110];
 6 long long n,j,V,W,S,num,hh1,ll1,hh2,ll2,T;
 7 char a,b;
 8 int main()
 9 {
10     cin>>hh1>>a>>ll1>>hh2>>b>>ll2>>n;
11     T=(hh2-hh1)*60+(ll2-ll1);
12     //cout<<hh1<<a<<ll1<<hh2<<b<<ll2<<endl;
13    // cout<<T<<endl;
14     for(int i=0;i<n;i++)
15     {
16         cin>>W>>V>>S;
17         if(!S)S=999999999;
18             for(int j=1;j<=S;j*=2)//二进制优化
19             {
20                 v[num]=V*j;
21                 w[num++]=W*j;
22                 S-=j;
23             }
24             if(S)//判断是否剩余
25             {
26                 v[num]=S*V;
27                 w[num++]=S*W;
28             }
29     }
30     for(int i=0;i<num;i++)//货物
31     {
32         for(int j=T;j>=w[i];j--)
33         {
34             DP[j]=max(DP[j-w[i]]+v[i],DP[j]);
35         }
36     }
37    // for(int i=0;i<=T;i++)
38     cout<<DP[T]<<endl;
39 }
复制代码

3.摆花

题目链接:P1077 [NOIP2012 普及组] 摆花 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

DP,多重背包问题,背包问题求方案数

将花盆数量看作背包容量;
将花看作物品,体积是1,第 ii 种物品最多选 aiai 个;
问题:将背包装满的方案数是多少?

复制代码
 1 #include <iostream>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int N = 110, mod = 1000007;
 7 
 8 int n, m;
 9 int f[N];
10 
11 int main()
12 {
13     cin >> n >> m;
14 
15     f[0] = 1;
16     for (int i = 0; i < n; i ++ )
17     {
18         int a;
19         cin >> a;
20         for (int j = m; j >= 0; j -- )
21             for (int k = 1; k <= j && k <= a; k ++ )
22                 f[j] = (f[j] + f[j - k]) % mod;
23     }
24 
25     cout << f[m] << endl;
26 
27     return 0;
28 }
复制代码

4.金明的预算方案

分组背包

在枚举四种组合时可以使用二进制的思想,可以简化代码。

题目链接:P1064 [NOIP2006 提高组] 金明的预算方案 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
 1 #include <cstring>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <vector>
 5 
 6 #define v first
 7 #define w second
 8 
 9 using namespace std;
10 
11 typedef pair<int, int> PII;
12 
13 const int N = 60, M = 32010;
14 
15 int n, m;
16 PII master[N];
17 vector<PII> servent[N];
18 int f[M];
19 
20 int main()
21 {
22     cin >> m >> n;
23 
24     for (int i = 1; i <= n; i ++ )
25     {
26         int v, p, q;
27         cin >> v >> p >> q;
28         p *= v;
29         if (!q) master[i] = {v, p};
30         else servent[q].push_back({v, p});
31     }
32 
33     for (int i = 1; i <= n; i ++ )
34         for (int u = m; u >= 0; u -- )
35         {
36             for (int j = 0; j < 1 << servent[i].size(); j ++ )
37             {
38                 int v = master[i].v, w = master[i].w;
39                 for (int k = 0; k < servent[i].size(); k ++ )
40                     if (j >> k & 1)
41                     {
42                         v += servent[i][k].v;
43                         w += servent[i][k].w;
44                     }
45                 if (u >= v) f[u] = max(f[u], f[u - v] + w);
46             }
47     }
48 
49     cout << f[m] << endl;
50 
51     return 0;
52 }
复制代码

 

本文作者:Zac-saodiseng

本文链接:https://www.cnblogs.com/Zac-saodiseng/p/17006891.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Zac-saodiseng  阅读(734)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起