算法竞赛入门经典 例题9-3 硬币问题

/*算法竞赛入门经典  例题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;
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值