1. 程式人生 > 其它 >Educoder實驗五硬幣抽選問題

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