一、Problem
3 2
1 3
MAX=7
二、Solution
方法一:暴搜 + dp
- 定義狀態:
- 表示組成郵資值 i 所需要的最小郵票數
- 思考狀態轉移方程:
- 如果 ,則有 ,表示如果 與 組成的郵資值所需的郵票數比其它郵票組成所需的郵票數要少的話,更新即可
- 思考初始化:
- ,表示組成郵資值 1 使用 1 張 1 面值的郵票是最少方案
下面就是定義 dfs 邏輯了:
- dfs 的搜索範圍每次都以上一個郵資值 a[k-1] 爲開始,每次遞增 1,直到當前找到的最大郵資值。
- 剪枝 1:讓郵票的面值從 a[k-1] + 1 開始保持遞增,避免重複,當然特可以用 boolean[] vis 記錄某種面值的使用狀態。
- 剪枝 2:
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
int n, m, max, maxn = 2000, a[], res[], dp[], INF = 0x3f3f3f3f;
int get(int k) {
int val = 1;
for (int i = 1; i < maxn; i++) dp[i] = INF;
for (int i = 1; i <= k; i++) dp[a[i]] = 1;
while (dp[val] <= n) {
val++;
for (int i = 1; i <= k; i++) {
if (val > a[i] && dp[val-a[i]]+1 < dp[val])
dp[val] = dp[val-a[i]]+1;
}
}
return val;
}
void dfs(int k) {
int t = get(k-1);
if (k > m) {
if (t-1 > max) {
max = t-1;
for(int i = 1; i <= m; i++)
res[i] = a[i];
}
return;
}
for (int i = a[k-1]+1; i <= t; i++) {
a[k] = i;
dfs(k+1);
}
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
n = sc.nextInt(); m = sc.nextInt();
res = new int[maxn];
a = new int[maxn];
dp = new int[maxn];
a[1] = 1;
dfs(2);
for (int i = 1; i <= m; i++) System.out.printf("%d ", res[i]); System.out.println();
System.out.printf("MAX=%d", max);
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,