兩題都是 dp[n]。
原題:
https://cses.fi/problemset/task/1633
題意:
給 n(1 ≤ n ≤ 10^6)。用 1~6 的骰子和成 n,有多少種方式?對 1e9+7 取模。
解題思路:
#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000007;
int main(){
int n;
cin>>n;
vector<int> dp(n+1,0);
dp[0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=6;j++){
if(i-j>=0){
dp[i]=(dp[i]+dp[i-j])%MOD;
}
}
}
cout<<dp[n]<<"\n";
return 0;
}
原題:
https://cses.fi/problemset/task/1637
題意:
給 n(1 ≤ n ≤ 10^6)。每一步可把 n 減去它十進位表示中的一個非零數字。問把 n 變成 0 的最少步數。
解題思路:
#include <bits/stdc++.h>
using namespace std;
void digits(int x, vector<int>& buf) {
buf.clear();
while (x > 0) {
int d = x%10;
if (d != 0) buf.push_back(d);
x /= 10;
}
}
int main() {
int n;
cin >> n;
const int INF = 1e9;
vector<int> dp(n+1, INF);
dp[0] = 0;
vector<int> buf;
for (int i=1; i<=n; i++) {
digits(i, buf);
int best = INF;
for (int t=0; t<buf.size(); t++) {
int d = buf[t];
if (i-d >= 0) {
int cand = dp[i-d] + 1;
if (cand<best) best=cand;
}
}
dp[i] = best;
}
cout << dp[n] << "\n";
return 0;
}
原題:
https://leetcode.com/problems/climbing-stairs/description/
題意:
每步可走 1 或 2 階,爬到第 n 階有幾種走法?
解題思路:
f[n] = f[n-1] + f[n-2],f[0]=1,f[1]=1。
class Solution {
public:
int climbStairs(int n) {
long long a = 1, b = 1; // f[0], f[1]
for (int i = 2; i <= n; i++) {
long long c = a+b; // f[i]
a = b;
b = c;
}
return b;
}
};
原題:
https://leetcode.com/problems/house-robber/description/
題意:
nums[i] 為每棟房子的金額;不能搶相鄰兩棟。求最大收益。
解題思路:
class Solution {
public:
int rob(vector<int>& nums) {
long long prev2 = 0; // dp[0]
long long prev1 = nums.empty() ? 0 : nums[0]; // dp[1]
for (int i = 2; i <= nums.size(); i++) {
long long take = prev2 + nums[i-1];
long long skip = prev1;
long long cur = (take > skip) ? take : skip;
prev2 = prev1;
prev1 = cur;
}
return prev1;
}
};