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;
}