Find More Coins (30)

本文讲述了如何通过将背包问题转化为01背包形式,利用两种不同的编程实现思路解决给定N个硬币组成M值的问题,一种是递归与二分查找结合,另一种是动态规划方法,最终找到最小序列。
摘要由CSDN通过智能技术生成

1、题意

N个数,看看有没有能够组成M的,有的话输出该序列,有多个解,输出最小的序列

2、思路

2.1 一开始看到题目,不会做,想成了递归,把M逐渐根据a[i] 进行划分,再二分另一个数,受不了太蠢了

2.2 看题解发现是背包问题:标准的01背包,价值===体积,但是要记录一下选过哪些。

第一种思路,先看看能不能装满,不能就No Solution,能的话,再从小到达,看看不同阶段的体积是不是有选,前一个状态如果存在的话,就输出该价值的硬币,先总再分

第二种思路,在选的时候就记录选了什么硬币,到最后处理到M的时候,直接就能返回,一步到位

3、代码

3.1 代码一

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 10010,M = 110;
int n,m;
int a[N];
bool f[N][M];

int main()
{
	cin>>n>>m;
	for(int i = 1;i<=n;i++) cin>>a[i];
	sort(a + 1,a + n + 1,greater<int>());// 从大到小排序 
	f[0][0] = true;
	
	for(int i = 1;i<=n;i++)// 标准01背包 
		for(int j = 0;j<=m;j++)
		{
			f[i][j] = f[i-1][j];
			if(j>=a[i]) f[i][j] += f[i-1][j-a[i]];
		}
		
	if(!f[n][m]) puts("No solution");
	else
	{
		bool is_first = true;
		while(n)
		{//因为a是从大到小,要从后面开始 
			if(m>=a[n]&&f[n-1][m-a[n]])// 逐渐向前看前面状态是不是装了硬币 
			{
				if(is_first) is_first = false;
				else cout<<" ";
				cout << a[n];
				m -= a[n];
			}
			
			n--;
		}
	}
	return 0;
}

 3.2 代码二

#include<bits/stdc++.h>
using namespace std;
int a[10100],b[110];
vector<int> dp[110];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i = 0;i<n;i++)scanf("%d",&a[i]);
	sort(a,a+n);
	dp[0].push_back(0);
	for(int i = n-1;i>=0;i--)
		for(int j = m;j>=a[i];j--)	
			if(dp[j-a[i]].size()!=0)
			{
				dp[j] = dp[j-a[i]];
				dp[j].push_back(a[i]);
			}
	
	if(dp[m].size()==0)printf("No Solution\n");
	else
	{
		for(int i = dp[m].size()-1;i>=1;i--)printf("%d ",dp[m][i]);
	}
	return 0;
 } 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值