硬币问题

有 n 种硬币,面值分别为V1,V2,V3...Vn ,每种都有无限多。给定非负整数 S ,可以选用多少个硬币,使得面值之和恰好为 S ?输出硬币数目的最小值和最大值。

记忆化搜索:

#include <iostream>
#include <cstring>
using namespace std;
#define MAX 20005
int n, dp[MAX], vis[MAX], v[MAX];

int dp_max(int s)
{
	if(vis[s]) return dp[s];
	vis[s] = 1;
	int &ans = dp[s];
	ans = -1 << 30;
	for(int i = 1; i <= n; i++)
	{
		if(s >= v[i])
		{
			ans = max(ans, dp_max(s - v[i]) + 1);
		}
	}
	return ans;
}

int dp_min(int s)
{
	if(vis[s]) return dp[s];
	vis[s] = 1;
	int &ans = dp[s];
	ans = 1 << 30;
	for(int i = 1; i <= n; i++)
	{
		if(s >= v[i])
		{
			ans = min(ans, dp_min(s - v[i]) + 1);
		}
	}
	return ans;
}

void print_ans(int s)
{
	for(int i = 1; i <=n; i++)
	{
		if(s >= v[i] && dp[s] == dp[s - v[i]] + 1)
		{
			cout << i << " ";
			print_ans(s - v[i]);
			break;
		}
	}
}

int main()
{
	freopen("in.txt", "r", stdin);
	int s;
	cin >> n >> s;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
	}
	memset(dp, 0, sizeof(dp));
	memset(vis, 0, sizeof(vis));
	vis[0] = 1;
	cout << "max = " << dp_max(s) << endl;
	print_ans(s);
	cout << endl;

	memset(dp, 0, sizeof(dp));
	memset(vis, 0, sizeof(vis));
	vis[0] = 1;
	cout << "min = " << dp_min(s) << endl;
	print_ans(s);
	cout << endl;
	return 0;
}

递推实现:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 1000
#define INF (1 << 30)
int	Max[MAX], Min[MAX], v[MAX];
int n;

void print_ans(int *dp, int s)
{
	for(int i = 1; i <= n; i++)
	{
		if(s >= v[i] && dp[s] == dp[s - v[i]] + 1)
		{
			cout << i << " ";
			print_ans(dp, s - v[i]);
			break;
		}
	}
}

int main()
{
	freopen("in.txt", "r", stdin);
	int s;
	cin >> n >> s;
	for(int i = 1; i <= n; i++)
	{
		cin >> v[i];
	}
	Min[0] = Max[0] = 0;
	for(int i = 1; i <= s; i++)
	{
		Min[i] = INF;
		Max[i] = -INF;
	}
	for(int i = 1; i <= s; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			if(i >= v[j])
			{
				Min[i] = min(Min[i], Min[i - v[j]] + 1);
				Max[i] = max(Max[i], Max[i - v[j]] + 1);
			}
		}
	}
	cout << "min = " << Min[s] << endl;
	print_ans(Min, s);
	cout << endl;

	cout << "max = " << Max[s] << endl;
	print_ans(Max, s);
	cout << endl;
	return 0;
}


原文地址:https://www.cnblogs.com/lgh1992314/p/5835143.html