UVa 624 CD (0-1背包)

624 - CD

Time limit: 3.000 seconds

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=565

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

本文URL地址:http://www.bianceng.cn/Programming/sjjg/201410/45378.htm

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

PS:special judge

代码中的输出的反着来的,若要正着输出可用栈先存一下。

///我这样写纯粹是为了记忆
记录路径:vis[i++][j--] = max2(dp[j], dp[j - weight[i]] + price[i]));///max2是个给dp[j]赋最大值的bool类型的函数,当第二个参数>=第一个参数时返回true。
打印路径:printf2(vis[i--][j-=weight[i]]);///vis[i][j]为真时打印weight[i]。

完整代码:

/*0.019s*/

#include<cstdio>
#include<cstring>
const int maxn = 10005;  

int val[25], dp[maxn];
bool vis[25][maxn];  

int main()
{
    int n, m, i, j;
    while (~scanf("%d%d", &n, &m))
    {
        memset(dp, 0, sizeof(dp));
        memset(vis, 0, sizeof(vis));
        for (i = 0; i < m; ++i)
            scanf("%d", &val[i]);
        for (i = 0; i < m; ++i)
            for (j = n; j >= val[i]; --j)
                if (dp[j - val[i]] + val[i] >= dp[j])
                {
                    dp[j] = dp[j - val[i]] + val[i];
                    vis[i][j] = true;
                }
        j = n;
        for (i = m - 1; i >= 0; --i)
            if (vis[i][j])
            {
                printf("%d ", val[i]);
                j -= val[i];
            }
        printf("sum:%d\n", dp[n]);
    }
    return 0;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索dp
, number
, sum
, val
, The
have
途乐y624.0、624 92 0、途乐y624.0怎么样、dota2 背包 cd、0 1背包问题,以便于您获取更多的相关知识。

时间: 2024-10-02 01:08:17

UVa 624 CD (0-1背包)的相关文章

uva 562 Dividing coins (0/1背包)

点击打开链接uva 562 思路: 0/1背包 分析: 1 题目意思是有两个人分n个金币,要求最后两个人的金币差值最小 2 我们利用背包的思想即背包的总容量为金币总和的一半,去求出可以放入背包的最大的金币(这里其实就是某一个人能获得的最大的金币),那么最后的ans就是(sum-dp[sum/2])-dp[sum/2] 代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorit

poj 3211 Washing Clothes(0/1背包)

点击打开链接poj 3211 思路: 0/1背包 分析: 1 题目要求洗完n件衣服所需的最少的时间,并且必须洗完一种颜色才能跳到下一种 2 仔细想想这一题和uva上面的一道分金币非常的相似,由于要求必须洗完一种颜色才能跳到下一种,那么我们只要使得洗每一种颜色的时间最少那么总的就最少,那怎样才能够最少的时间呢?也就是要求两个人的时间差最小(也就相当于一个人用一半的时间去能够洗的最多的衣服),那么就转化为0/1背包的思想 3 做m次的dp然后求和即可 代码: #include<cstdio> #i

poj 1976 A Mini Locomotive(0/1背包)

点击打开链接poj 1976 思路: 0/1背包 分析: 1 题目给定n个数,要求三段连续的m个数之和最大 2 假设n个数是num[1],num[2],num[3]......num[n],那么m个连续的数可能有n-m+1种可能即num[1]+num[2]...+num[k] , num[2]+num[3]...+num[k]...... 3 我们令v[1] = num[1]+num[2]...+num[k] , v[2] = num[2]+num[3]...+num[k].那么总的有n-m+1

hdu 2955 Robberies(0/1背包)

点击打开链接hdu 2955 思路: 0/1背包 分析: 1 按照题目的意思我们很容易知道这就是一个0/1背包问题,如果我们把概率当作是背包的容量,那么我们遇到一个问题就是浮点数的dp,因为题目没有告诉我们小数点具体几位,那么我们就不能够通过乘上10^n来转化为整数,所以我们应该考虑换种思想 2 按照正常的思路是dp[i][j]表示前i个物品放入概率为j的最大价值,那么我们这边把价值当成背包来看的话我们设dp[i][j]表示前i个物品放入金钱为j的最小被抓概率(因为题目不好求最小概率我们可以认为

poj 1948 Triangular Pastures(二维0/1背包)

点击打开链接poj 1948 思路: 二维0/1背包 分析: 1 题目要求从n个木棒里面选出m个组成一个三角形,使得三角形的面积最大 2 对于三角形来说知道了两条边和周长就可以求面积,按照0/1背包的思想dp[i][j][k]表示前i个木棒能否组成第一条边为长度j,第二条长度为k.如果dp[j-v[i]][k] 或dp[j][k-v[i]] 为true则dp[j][k]就为true 3 我们求出了所有可能的组合之和,就去枚举所有的边长的情况,然后求最大的面积 代码: #include<cmath

hdu 3466 Proud Merchants(0/1背包)

点击打开链接hdu 3466 思路: 0/1背包 分析: 1 这一题和"hdu2546 饭卡"有点像,但是又有不同,不同的是这一题每一个物品都有一个限制的值Q[i],求最大的价值 2 题目明确提到每一种物品只能卖一次或这不卖,那这明显就是0/1的性质,但是现在多了一个条件钱不能少于Q[i].这边的话我各种YY无果之后,果断看了题解,发现是要按照q-p排序,然后再做dp. 3 经过一番的YY之后,我明白了为什么按照q-p是正确的.我们都知道dp有一个很重要的特点就是无后效性,如果没有金钱

poj 3624 Charm Bracelet (0/1背包)

点击打开链接 裸0/1背包 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 15000; int n , m; int w[MAXN] , v[MAXN] , dp[MAXN]; int main(){ while(scanf("%d%d" , &n , &

hdu 2639 Bone Collector II (0/1背包)

点击打开链接hdu 2639 思路: 0/1背包求第k优解 分析: 1 其基本思想是,将每个状态都表示成有序队列,将状态转移方程中的 max/min 转 化成有序队列的合并. 2 这里仍然以 01 背包为例讲解一下.    首先看 01 背包求最优解的状态转移方程: F [i, v] = max{F [i − 1, v], F [i − 1, v −Ci ] + Wi }.如果要求第 K 优解,那么状态 F [i, v] 就应该是一个大小为 K 的队列F [i, v, 1 . . . K].其中

hdu 2126 Buy the souvenirs(二维0/1背包)

点击打开链接hdu2126 思路: 二维0/1背包 分析: 1 题目给定n个物品的价钱和m的钱,问最多能买到的物品数有几种方案. 2 很明显就可以写出状态转移方程dp[i][j][k]表示的是前i个物品选j个总价钱为k的方案数 那么dp[i][j][k] = dp[i-1][j][k]+dp[i-1][j-1][k-v[i]].由于都可以把第一维去掉,所以正常的情况下直接写出dp[j][k] = dp[j][k] + dp[j-1][k-v[i]] 代码: #include<cstdio> #