/*算法竞赛入门经典 例题9-3 硬币问题
* d[i]表示从i出发到结点0的最长路径长度 d[0]=0
* 固定起点s 固定终点0
* 状态转移方程: d[i] = max{d[j] + 1}
* */
import java.util.Arrays;
import java.util.Scanner;
public class Coins {
static final int MAX = 1<<30;
static final int MIN = -MAX;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Coins c = new Coins();
int n = scanner.nextInt();
int[] v = new int[n+1];//0不使用
for(int i=1; i<=n; i++) {
v[i] = scanner.nextInt();
}
int s = scanner.nextInt();
int[] d = new int[s+1];
Arrays.fill(d, -1);
d[0] = 0;// d[0]必须初始化为0
/*
boolean[] isFound = new boolean[]{false};
c.dp(s,d,v,isFound);
if(!isFound[0]) {
System.out.println("no answer!");
}else {
c.print(d, s, v);
}
*/
//递推法
int[] min = new int[s+1];
int[] max = new int[s+1];
Arrays.fill(min, MAX);
Arrays.fill(max, MIN);
min[0] = max[0] = 0;
for(int i=1; i<=s; i++) {
for(int j=1; j<=n; j++) {
if(i >= v[j]) {
min[i] = min[i] < min[i-v[j]] + 1 ? min[i] : min[i-v[j]] + 1;
max[i] = max[i] > max[i-v[j]] + 1 ? max[i] : max[i-v[j]] + 1;
}
}
}
c.print(min, s, v);
System.out.println();
c.print(max, s, v);
}
//记忆化搜索
int dp(int s, int[] d, int[] v, boolean[] isFound) {
if(s == 0) isFound[0] = true;
if(d[s] != -1) return d[s];
d[s] = MIN;
for(int i=1; i<v.length; i++) {
if(s >= v[i]) {
int temp = dp(s-v[i],d,v,isFound) + 1;
d[s] = d[s] > temp ? d[s] : temp;
}
}
return d[s];
}
void print(int[] d, int s, int[] v) {
int i;
for(i=1; i<v.length; i++) {
if(s>=v[i] && d[s] == d[s-v[i]] + 1) {
System.out.printf("%d ",i);
print(d,s-v[i],v);
break;
}
}
}
}
算法竞赛入门经典 例题9-3 硬币问题
最新推荐文章于 2023-11-23 19:43:10 发布