任务说明
本关任务:编写动态规划法算法,求解硬币抽选问题。
相关知识
为了完成本关任务,你需要了解实验目的和实验内容。
实验目的
(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;
}