动态规划----硬币问题

问题描述:


这是一个固定重点的最长路和最短路问题,可用动态规划问题来求解


方法一:递归


动态规划----硬币问题_第1张图片

源代码

#include 
#include 
#include

using namespace std;

const int MAXN = 10000;
const int INF = 100000000;
//代表硬币总值,n代表硬币总数,V数组保存硬币各个面值, d代表从i出发到结点0的路径的最长路径长度或最短路径长度
//vis代表是否访问过该结点
int n, S, V[MAXN], d[MAXN], vis[MAXN];

int dpmax(int S) {
	if (vis[S]) return d[S];
	vis[S] = 1;
	int &ans = d[S];
	ans = -(1<<30);//(1 << 30);
	for (int i = 1; i <= n; ++i) {
		if (S >= V[i]) ans = max(ans, dpmax(S - V[i]) + 1);
	}
	return ans;
}

int dpmin(int S)
{
	if (vis[S]) return d[S];
	vis[S] = 1;
	int &ans = d[S];
	ans = (1 << 30);
	for (int i = 1; i <= n; ++i)
	{
		if (S >= V[i])
			ans = min(ans, dpmin(S - V[i]) + 1);
	}

	return ans;
}

int main() {
	//int num = -(int)((unsigned)~0 >> 1) - 1;
	//int num = ~0;//(int)((unsigned)~0 );
	//cout << num << "   "<> n >> S;
	for (int i = 1; i <= n; ++i) {
		cin >> V[i];//硬币面值
	}
	cout << dpmax(S) << endl;

	memset(vis, 0, sizeof(vis));
	memset(d, 0, sizeof(d));
	vis[0] = 1;
	cout << dpmin(S) << endl;
	system("pause");
	return 0;
}

运行结果:
3 600
2 3 5
300
120
请按任意键继续. . .


方法二:递推并打印路径

动态规划----硬币问题_第2张图片

源代码:

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include

#define MAXN  10000
#define INF  100000000

int minv[MAXN], maxv[MAXN], n, S, V[MAXN];
int min_coin[MAXN] = { 0 }, max_coin[MAXN] = { 0 };

void print_ans(int *d, int S)
{
	while (S)
	{
		printf("%d  ", V[d[S]]);
		S -= V[d[S]];
	}
}

int main()
{
	V[0] = 0;
	if (scanf("%d %d", &n, &S) == 2)
	{
		for (int i = 1; i <= n; i++)
		{
			if (scanf("%d", &V[i]) != 1)
				return -1;
		}

		//memset(minv, 1, sizeof(int)*S);
		//memset(maxv, -1, sizeof(int)*S);

		for (int i = 1; i <= S; ++i)
		{
			minv[i] = INF;
			maxv[i] = -INF;
		}
		minv[0] = maxv[0] = 0;

		for (int i = 1; i <= S; ++i)
		{
			for (int j = 1; j <= n; ++j)
			{
				if (i >= V[j])
				{
					if (minv[i] > minv[i - V[j]] + 1)
					{
						minv[i] = minv[i - V[j]] + 1;
						min_coin[i] = j;
					}

					if (maxv[i] < maxv[i - V[j]] + 1)
					{
						maxv[i] = maxv[i - V[j]] + 1;
						max_coin[i] = j;
					}

					/*minv[i] = min(minv[i], 1 + minv[i - V[j]]);
					maxv[i] = max(maxv[i], 1 + maxv[i - V[j]]);*/
				}
			}
		}
		printf("最短路径为:%d, 分别为:", minv[S]);
		print_ans(min_coin, S);
		printf("\n最短路径为:%d, 分别为:", maxv[S]);
		print_ans(max_coin, S);
		printf("\n");
		
	}
	printf("%s  %s\n", __DATE__, __TIME__);
	system("pause");
	return 0;
}

运行结果:
3 6
2 3 5
最短路径为:2, 分别为:3  3
最短路径为:3, 分别为:2  2  2
Aug 24 2016  23:48:03
请按任意键继续. . .






你可能感兴趣的:(算法)