本題其實是一個 \(01\) 揹包的板子題,除了題目背景不同以外,其它的都一模一樣!
- \(1\)、狀態:
定義一個二維陣列 f,\(f_{i\ j}\)表示前 \(i\) 種採藥,時間為 \(j\) 時可以獲得的最大價值。
- \(2\)、狀態轉移方程:
我們設當前時間為 \(j\) 採完這個草藥需要的時間 \(t\),採摘這個草藥可以獲得的價值為 \(w\)。則分兩種情況:
\(1.\) 如果 \(j \ge t\),那麼可以選這個草藥,也可以不選:\(f_{i\ j} = max(f_{i-1\ j}, \ f_{i-1\ j-t}+w)\)
\(2.\) 那麼如果 \(j < t\),那麼不能選這個草藥:\(f_{i\ j} = f_{i-1\ j}\)
- \(3\)、初始化
由於如果當前時間為 \(0\),那麼你是永遠也湊不出來一個值的,所以 \(f_{i\ 0} = 0\)
- \(4\)、答案
我們最後要求時間為 \(T\) 時,求最大利益,那麼也就是 \(max(f_{i\ T})(1 \le i \le n)\)
程式碼:
#include <bits/stdc++.h>
using namespace std;
int T, m, ans, f[110][1010]; //f[i][j]表示前i種草藥時間為j時能採摘到達最大價值
struct node {
int t, w; //一個草藥需要花費時間和得到價值
}a[110];
int main() {
cin >> T >> m;
for (int i = 1; i <= m; i++)
cin >> a[i].t >> a[i].w;
for (int i = 1; i <= m; i++)
f[i][0] = 0; //初始化
for (int i = 1; i <= m; i++)
for (int j = 1; j <= T; j++)
if(j >= a[i].t) f[i][j] = max(f[i - 1][j], f[i - 1][j - a[i].t] + a[i].w); //如果時間充足,則需要考慮選或不選
else f[i][j] = f[i - 1][j]; //否則不選
for (int i = 1; i <= m; i++)
ans = max(ans, f[i][T]); //找最佳答案
cout << ans << endl;
return 0;
}