【东东开车了】01背包+回溯

题目

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

题目大意

本题给出开车出行总时间以及若干张CD每张播放的时间,要求我们选择heshideCD使得消磨开车时间最长,并且需要给出选择方案。

解题思路

本题是在01背包问题的基础上要求我们输出一种选择方案,其关键也是难点就在方案的回溯上。动态规划的回溯问题也是一类需要学会记忆的内容,此处的回溯过程可以当做模板记忆,方便以后使用。

具体代码

#include<iostream>
#include<sstream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdio>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<map>
#define MAXN 100005
#define ll long long

using namespace std;

int value[25],f[25][10005];

void solve(int a, int b)
{
	if(a == 0 || b == 0)
	{
		return;
	}
	if(f[a][b] == f[a-1][b])  //没选 
	{
		solve(a-1,b);
	}
	else if(f[a][b] == f[a-1][b-value[a]]+value[a])  //选择 
	{
		printf("%d ",value[a]);
		solve(a-1,b-value[a]);
	}
}

int main()
{
    ios::sync_with_stdio(false);
    int t,m;
    while(cin >> t >> m)
    {
    	memset(f,0,sizeof(f));
    	for(int i = 1; i <= m; i++)
    	{
    	    cin >> value[i];
    	}
    	for(int i = 1; i <= m; i++)
    	{
    	    for(int j = t; j >= 0; j--)
    	    {
    	        if(j >= value[i])
    	        {
    	        	f[i][j] = max(f[i-1][j],f[i-1][j-value[i]]+value[i]);
    	        }
    	        else
    	        {
    	            f[i][j] = f[i-1][j];
    	        }
    	    }
    	}
    	solve(m,t);
    	printf("sum:%d\n",f[m][t]);
	}
    return 0;
}
原创文章 46 获赞 1 访问量 1490

猜你喜欢

转载自blog.csdn.net/weixin_43676449/article/details/105863764