0-1背包东东听CD

问题描述

东东开车出去泡妞(在梦中),车内提供了 n 张CD唱片,已知东东开车的时间是 n 分钟,他该如何去选择唱片去消磨这无聊的时间呢
假设:
CD数量不超过20张
没有一张CD唱片超过 N 分钟
每张唱片只能听一次
唱片的播放长度为整数
N 也是整数
我们需要找到最能消磨时间的唱片数量,并按使用顺序输出答案(必须是听完唱片,不能有唱片没听完却到了下车时间的情况发生)
【输入】
多组输入
每行输入第一个数字N, 代表总时间,第二个数字 M 代表有 M 张唱片,后面紧跟 M 个数字,代表每张唱片的时长 例如样例一: N=5, M=3, 第一张唱片为 1 分钟, 第二张唱片 3 分钟, 第三张 4 分钟
所有数据均满足以下条件:N≤10000 M≤20
【输出】
输出所有唱片的时长和总时长,具体输出格式见样例
【样例输入】

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

【样例输出】

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

问题分析

关于0-1背包
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这道题中,开车时间=背包容量,CD个数=物品个数,CD时间长短=物品价值
选择总时间最长且大于开车时间的CD选择方案,则使用0-1背包问题解决这道题
由于本题需要记录路径,故不能使用一维数组进行空间优化
在最后一组数据中的sum:45,不一定是题目所给的组合也可能是43+2

#include<iostream>
 
using namespace std;
int v[25];
int dp[25][10005]; 
int ans[25];
int N,M;
int main()
{
	while(scanf("%d",&N)!=EOF)//总时间,唱片的数量
	{
		cin>>M;
		for(int i=1;i<=M;i++)
		{
			cin>>v[i];
		} 
		for(int i=0;i<=N;++i)
	    {
			dp[0][i]=0;
		}
		for(int i=1;i<=M;++i)
		{
			for(int j=0;j<=N;++j)
			{
				dp[i][j]=dp[i-1][j];
				if(j-v[i] >= 0)
				{
					dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+v[i]);
				}
			}
		}
		int w=dp[M][N];
		for(int i=M;i>1;i--)
		{
			if(dp[i][w]==dp[i-1][w])
				ans[i]=0;
			else
			{
				ans[i]=1;
				w-=v[i];
			}	
		}
		if(dp[1][w]>0)
			ans[1]=1;
		else 
		    ans[1]=0;	//前几次赋值影响结果 
		for(int i=1;i<=M;i++)
		{
			if(ans[i])
				cout<<v[i]<<" ";
		}
		cout<<"sum:"<<dp[M][N]<<endl;
    }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值