原題:
https://cses.fi/problemset/task/1158
題意:
n 本書,每本價格 h[i]、頁數 s[i],預算 x,求最多能拿到幾頁。
解題思路:
0/1 背包;容量倒序更新。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, x;
cin >> n >> x;
vector<int> h(n), s(n);
for (int i=0; i<n; i++) cin >> h[i];
for (int i=0; i<n; i++) cin >> s[i];
vector<int> dp(x+1, 0); // dp[c] = 在預算 c 下的最大頁數
for (int i = 0; i < n; i++) {
for (int c = x; c >= h[i]; c--) {
dp[c] = max(dp[c], dp[c - h[i]] + s[i]);
}
}
cout << dp[x] << "\n";
return 0;
}
原題:
https://cses.fi/problemset/task/1635
題意:
給 n 種硬幣面額與目標和 x,問有幾種序列(順序視為不同)能湊成 x,答案對 1e9+7 取模。
解題思路:
排列計數 → 外層容量、內層硬幣;dp[0]=1。
#include<bits/stdc++.h>
using namespace std;
const int MOD=1000000007;
int main(){
int n,x;
cin>>n>>x;
vector<int> coin(n);
for(int i=0;i<n;i++){
cin>>coin[i];
}
vector<int> dp(x+1,0);
dp[0]=1; //0元:都不拿
// 順序有差:金額在外,硬幣在內
// 要湊 9,最後一枚是 5 → 需要湊 4 (2+2)
// → 組合 = 2+2+5
// 要湊 9,最後一枚是 2 → 需要湊 7 (2+5 or 5+2)
// → 組合 = 2+5+2, 5+2+2
for(int i=1;i<=x;i++){
long long ways=0;
for(int c:coin){
if(i>=c){
ways+=dp[i-c];
}
}
dp[i]=ways%MOD;
}
cout<<dp[x]<<endl;
return 0;
}
原題:
https://leetcode.com/problems/partition-equal-subset-sum/description/
題意:
能否把陣列分成兩個子集且總和相等?
解題思路:
class Solution {
public:
bool canPartition(vector<int>& nums) {
long long S = 0;
for (int v:nums) S+=v;
if (S % 2) return false;
int target = (S/2);
vector<char> dp(target+1, 0);
dp[0] = 1;
for (int v : nums) {
for (int s = target; s>=v; s--) {
dp[s] = dp[s] || dp[s-v];
}
}
return dp[target];
}
};
原題:
https://leetcode.com/problems/coin-change-ii/
題意:
用硬幣組成 amount 的組合數(順序不重要)。
解題思路:
外層硬幣、內層容量正序;dp[0]=1。
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<unsigned long long> dp(amount+1, 0);
dp[0] = 1;
for (int c : coins) { // 組合:外層枚舉硬幣
for (int s = c; s <= amount; s++) { // 容量正序允許同幣多次
dp[s] += dp[s-c];
}
}
return dp[amount];
}
};