題解:2018級演算法第二次上機 Zexal的競賽
- 2019 年 10 月 18 日
- 筆記
題目描述:
樣例:
實現解釋:
一道需要一點思考的動態規劃題目
知識點:動態規劃,數據記錄
首先將題目描述調整:分別輸入不同分數的題目總分(便於後續計算),當獲得了i分數的總分後無法獲得i-1和i+1的總分。
於是便可先利用score[i]儲存i分數的總分數,用dp[i]儲存以前i個分數為範圍進行題目選擇時的最大可獲得分數。dp便是動態規劃所用的數組。
於是可得狀態轉移方程如下:
dp[0] = score[0]; dp[1] = score[1];
dp[i] = max(dp[i-2]+score[i],dp[i-1]);
0和1分直接初始化,而選擇前i個分數時的最大分數有兩種選擇:1.選擇前i-1個分數時的最大分數,2.選擇前i-2個分數時的最大分數加上當前分數的總分。
完善為完整的程式碼即可。
坑點:
多組輸入時需要重置score數組為0
考慮到dp是從前向後進行,因此注意要重置dp數組的0和1處的值
完整程式碼:
//動態規劃 zexal的競賽 #include <iostream> #include <algorithm>//引用max函數 using namespace std; long long dp[100010]; long long score[100010]; //注意如果多次輸入需要對score進行清空處理 int main() { ios::sync_with_stdio(false); int n,s; cin >> n;//題目個數 int top = 0;//最大的題目分數,防止無用的遍歷 for (int i = 0;i<n;i++) { cin >> s; score[s]+=s;//出現x次,則做完為x*s分 if(s>top) top = s; } dp[0] = score[0]; dp[1] = max(score[0],score[1]); for(int i = 2;i<=top;i++) { //具體狀態轉換方程見實現解釋 dp[i] = max(dp[i-2]+score[i],dp[i-1]); } //以所有分數題目為範圍的最大分數 cout << dp[top] << 'n'; }


