Educoder实验五硬币抽选问题

任务说明
本关任务:编写动态规划法算法,求解硬币抽选问题。

相关知识
为了完成本关任务,你需要了解实验目的和实验内容。

实验目的
(1)熟悉动态规划法的基本设计思想。

(2)掌握动态方程的推导过程。

(3)掌握硬币抽选问题的动态规划法算法。

实验内容
硬币抽选问题:将若干叠硬币排成一行,每一叠硬币的价值为整数,标记为c1,c2,…,cn,每一叠的硬币的价值无序,并且可能存在重复值。抽选硬币时,一次抽取一叠硬币,且不能抽取相邻叠的硬币。硬币抽选问题的目标就是从c1…,cn中选出价值最高的组合。

例如:6叠硬币排成一行,其价值分别为:5, 1, 2, 10, 6, 2,硬币抽选问题的抽选结果为5, 10, 2,其总价值为17。

实验原理
(1)用F(n)表示抽选硬币的最大价值,则F(n)的值可能是以下两种情况之一:

抽选了第n叠硬币,第n-1叠硬币不能选,F(n)的值是前n-2叠硬币抽选的最大价值加上第n叠硬币的价值,即:F(n)=F(n-2)+cn;

没有抽选第n叠硬币,F(n)的值是前n-1叠硬币抽选的最大价值,即:F(n)=F(n-1);

(2)由以上分析,可以推出硬币抽选问题的动态方程为:

在这里插入图片描述

(3)用一个一维数组记录F(n)随n值变化的情况,即可得到硬币抽选问题的解。

实验步骤
(1)详细阅读问题描述,理解问题;

(2)手工求解问题,得到示例输入的预期结果;

(3)设计算法,求解问题;

(4)编写算法程序;

(5)调试、运行程序,保证程序正确输出预期结果;

(6)分析程序的运行情况及算法效率。

编程要求
仔细阅读右侧编辑器中代码框架,在Begin-End之间补充完整void coin_row(int n, struct coin C[], int F[])函数,完成硬币抽选问题,并分析你的算法效率及优缺点。

测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:

测试输入:

6
5 1 2 10 6 2
预期输出:

Select coins: 5 10 2
The values of the selected coins: 17

#include <stdio.h>
#include <string.h>
#define MAX 100
void coin_row(int n, int C[], int F[], int P[][MAX]) 
{
	/**********  Begin  **********/
	//在此处填写算法代码
	int i;
	F[0]=0,F[1]=C[1];
	for( i=2; i<=n; i++)
	{
		if(F[i-2]+C[i]>F[i-1])
			F[i]=F[i-2]+C[i];
		else
			F[i]=F[i-1];
	}
	int nn=n;
	while(nn)
	{
		if(nn==1)
		{
			P[n][nn]=1;
			nn=nn-1;
		}
		else if(F[nn-2]+C[nn]>F[nn-1])
		{
			P[n][nn]=1;
			P[n][nn-1]=0;
			nn=nn-2;
		}
		else
		{
			P[n][nn-1]=1;
			P[n][nn]=0;
			nn=nn-1;
		}
	}
	/**********  End  **********/

}

void set_values(int *n, int C[])
{
	scanf("%d", n);
	int i;
	for (i = 1; i <= *n; i++) scanf("%d", &C[i]);
}
void show_result(int n, int C[], int F[], int P[][MAX])
{
	int i;
	printf("Select coins: ");
	for (i = 1; i <= n; i++)
		if (P[n][i])
			printf("%d ", C[i]);
	printf("\n");
	printf("The values of the selected coins: %d\n", F[n]);
}
int main()
{
	int n;
	int C[MAX];
	int F[MAX];

	int P[MAX][MAX];
	memset(P, 0, sizeof(P)); 
	set_values(&n, C);
	coin_row(n, C, F, P);
	show_result(n, C, F, P);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值