UVA 624CD(01背包输出 + 输出路径)

You have a long drive by car ahead. You have a tape recorder, but unfortunately your best music is on
CDs. You need to have it on tapes so the problem to solve is: you have a tape N minutes long. How
to choose tracks from CD to get most out of tape space and have as short unused space as possible.
Assumptions:
• number of tracks on the CD does not exceed 20
• no track is longer than N minutes
• tracks do not repeat
• length of each track is expressed as an integer number
• N is also integer
Program should find the set of tracks which fills the tape best and print it in the same sequence as
the tracks are stored on the CD
Input
Any number of lines. Each one contains value N, (after space) number of tracks and durations of the
tracks. For example from first line in sample data: N = 5, number of tracks=3, first track lasts for 1
minute, second one 3 minutes, next one 4 minutes
Output
Set of tracks (and durations) which are the correct solutions and string ‘sum:’ and sum of duration
times.
Sample Input
5 3 1 3 4
10 4 9 8 4 2
20 4 10 5 7 4
90 8 10 23 1 2 3 4 5 7
45 8 4 10 44 43 12 9 8 2
Sample Output
1 4 sum:5
8 2 sum:10
10 5 4 sum:19
10 23 1 2 3 4 5 7 sum:55
4 10 12 9 8 2 sum:45

题意:求和最大的,弄了两个小时没鼓捣出来=_=

两种方法:一种是二维的dp[i][j] 表示前 i 种体积为 j 的最大价值量,那么对于 dp[i][j] = dp[i - 1][j]就一定不输出咯,因为这个表示第i个没选

第二种对于一维的来说:dp[i]表示 体积 为 i 的最大价值量,然后可以设一个数组来记录

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cstdio>
 5 using namespace std;
 6 const int Max = 1000 + 10;
 7 int trak[Max], dp[Max * 20];
 8 int vis[Max * 20][Max];
 9 int vistrak[Max];
10 int main()
11 {
12     int n;
13     while (scanf("%d", &n) != EOF)
14     {
15         int traks;
16         scanf("%d", &traks);
17         for (int i = 1; i <= traks; i++)
18             scanf("%d", &trak[i]);
19         memset(vis, 0, sizeof(vis));
20         memset(dp, 0, sizeof(dp));
21         memset(vistrak, 0, sizeof(vistrak));
22         for (int i = 1; i <= traks; i++)
23         {
24             for (int j = n; j >= trak[i]; j--)
25             {
26                 if (dp[j] <= dp[j - trak[i]] + trak[i])
27                 {
28                     dp[j] = dp[j - trak[i]] + trak[i];
29                     vis[j][i] = trak[i];  // 体积为 j 时选 i 的价值
30                 }
31             }
32         }
33         int tempn = n;
34         for (int i = traks; i > 0; i--)
35         {
36             if (vis[tempn][i])  // 如果选了就应该是输出的,
37             {
38                 vistrak[i] = 1;
39                 tempn -= vis[tempn][i];
40             }
41         }
42         for (int i = 1; i <= traks; i++)
43         {
44             if (vistrak[i])
45                 printf("%d ", trak[i]);
46         }
47         printf("sum:%d\n", dp[n]);
48     }
49     return 0;
50 }

时间: 2024-09-30 01:59:45

UVA 624CD(01背包输出 + 输出路径)的相关文章

UVa CD 0-1背包且打印路径

就是简单的0-1背包问题,不过没有具体的效益值,隐含的效益值就是剩余背包的容量.因为要输出具体选择了那些track(也就是物品),所以采用序偶的方法.其实0-1背包的解画在坐标轴上就是一个分段函数,所谓序偶就是那些跃迁的节点.但是这道题略有不同,第0阶段的初始序偶不是(0,0),而是(0,N).序偶的第一个参数表示容量,第二个参数表示背包的剩余容量.当由前一阶段的序偶得到新序偶,并且将两者合并的时候.应当按照序偶的第一个参数从小到大进行合并,如果下一个要合并的序偶的剩余容量大于当前最后一个以合并

UVa 12563 (01背包) Jin Ge Jin Qu hao

如此水的01背包,居然让我WA了七次. 开始理解错题意了,弄反了主次关系.总曲目最多是大前提,其次才是歌曲总时间最长. 题意: 在KTV房间里还剩t秒的时间,可以从n首喜爱的歌里面选出若干首(每首歌只能唱一次且如果唱就必须唱完),然后剩下至少1秒的时间来唱那首长678秒的歌曲. 总曲目最多的前提下,尽量使歌曲总时间最长. 分析: 所给时间为t,在t-1秒内进行01背包,num[i]来记录剩余时间为 i 时能长的最多曲目,如果曲目相同还要记录最长时间. 1 //#define LOCAL 2 #i

uva624 01背包要求输出路径

You have a long drive by car ahead. You have a tape recorder, but unfortunately your best music is onCDs. You need to have it on tapes so the problem to solve is: you have a tape N minutes long. Howto choose tracks from CD to get most out of tape spa

POJ 1015 / UVA 323 Jury Compromise(01背包,打印路径)

POJ1015?UVA323?参考文章 (博主看了几篇文章,但是都没有考虑到背包容量的越界问题,关于这个,会在代码里解释.顺便提一下,POj这题的数据是比较弱的,建议去UVA 323检测一下代码的正确性) 题目大意:给出$n$对数,从中选出$m$对数,使各对数的差累加和最小的情况下总和最大. ??设每对数的差值为$sub[i]$,和为$sum[i]$.要从中选出m个数,对于每个数来说,都有选与不选两种情况,所以能不能用背包来做呢?用背包的话还得确定容量.既然题目要求$sub$的总和最小的情况下$

UVA 624(01背包记录路径)

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=565 记录路径可以用一个二维数组,记录改变时的量.然后从后往前可以推得所有的值. #include <iostream> #include <string> #include <cstring> #include <cstdlib> #incl

Re0:DP学习之路 01背包如何打印路径?

伪代码 用二维数组记录,如果出现可以转移的dp那么记录bk[当前体积][装的物品]=1 输出的时候倒推,如果存在连通的边那么输出并且总共的体积减去输出的体积 代码(uva-624,目前wa不明所以,网上的答案也是那么输出的,或许要输出最多的物品?目前也不会这种玩法) #include <bits/stdc++.h> using namespace std; int v[1000],dp[1000000],bk[1000][1000]; int main() { ios::sync_with_s

UVa 1213 (01背包变形) Sum of Different Primes

题意: 选择K个质数使它们的和为N,求总的方案数. 分析: 虽然知道推出来了转移方程, 但还是没把代码敲出来,可能基本功还是不够吧. d(i, j)表示i个素数的和为j的方案数,则 d(i, j) = sigma d(i-1, j-p[k]) ,其中p[k]表示第k个素数 注意递推的顺序是倒着推的,否则会计算重复的情况. 代码中第二重和第三重循环的顺序可互换. 1 #include <cstdio> 2 #include <cmath> 3 4 const int maxp = 1

vijos 1071 01背包+输出路径

描述 过年的时候,大人们最喜欢的活动,就是打牌了.xiaomengxian不会打牌,只好坐在一边看着. 这天,正当一群人打牌打得起劲的时候,突然有人喊道:“这副牌少了几张!”众人一数,果然是少了.于是这副牌的主人得意地说:“这是一幅特制的牌,我知道整副牌每一张的重量.只要我们称一下剩下的牌的总重量,就能知道少了哪些牌了.”大家都觉得这个办法不错,于是称出剩下的牌的总重量,开始计算少了哪些牌.由于数据量比较大,过了不久,大家都算得头晕了. 这时,xiaomengxian大声说:“你们看我的吧!”于

UVA 624 CD (01背包 带路径)

题意 输入两个数 len,n 表示长度和个数,接下来输入n个数, 表示每一个的长度, 求这n个数能够组成的不超过len的最大长度,并输出这些数. 分析:01背包,dp数组非0表示可以组成的数,dp数组用来记录路径 #include <iostream> #include <queue> #include <cstdio> #include <cstring> #include <cstdlib> #include <stack> #i