【JAVA】动态规划经典例题

钢条问题

public class 钢条问题 {
	public static void main(String[] args) {
		int[] p = { 0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30 };
		int n = 5;// 钢条长度
		int rn = max(n, p);
//		int[] baks=new int[p.length];
//		
//		//初始化备忘录
//		for(int i=0;i<baks.length;i++) {
//			baks[i]=-1;
//		}
//		int rn=max(n,p,baks);
		System.out.println(rn);
	}

//	/**
//	 * 递归求最优解
//	 * @param p
//	 * @param p
//	 * @return
//	 */
//	private static int max(int n, int[] p) {
//		if (n == 0)
//			return 0;
//		int maxPrice = 0;
//		for (int i = 1; i <= n; i++) {
//			int tempMax = p[i] + max(n - i, p);
//			if (tempMax > maxPrice) {
//				maxPrice = tempMax;
//			}
//		}
//		return maxPrice;
//	}
	
	
	
//	/**
//	 * 动态规划求最优解(备忘录法)
//	 * @param n
//	 * @param p
//	 * @param baks 
//	 * @return
//	 */
//	private static int max(int n, int[] p, int[] baks) {
//		if (n == 0)return 0;
//		if(baks[n]!=-1) {
//			return baks[n];
//		}
//		
//		int maxPrice = 0;
//		for (int i = 1; i <= n; i++) {
//			int tempMax = p[i] + max(n - i,p, baks);
//			if (tempMax > maxPrice) {
//				maxPrice = tempMax;
//			}
//		}
//		baks[n]=maxPrice;
//		return maxPrice;
//	}
	
	
	
	/**
	 * 自底向上求最优解
	 * @param n
	 * @param p
	 * @return
	 */
	private static int max(int n, int[] p) {
		int[] r=new int[n+1];//存储最优解的数组
		//数组最小值为0,故这里不用初始化。
		
		for(int i=1;i<=n;i++) {
			int maxPrice=0;
			for(int j=1;j<=i;j++) {
				int temp=p[j]+r[i-j];
				if(temp>maxPrice) {
					maxPrice=temp;
				}
			}
			r[i]=maxPrice;
		}
		return r[n];
	}
}

小Q拼凑硬币

//低效	import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

public classQ拼凑硬币 {
//低效	private static ArrayList<Long> mem = new ArrayList<Long>(Arrays.asList(1L,1L));
	
	//HashMap是存储和查找效率最高的数据结构,但是占用内存较大       
	//备忘录,存储每种面值n的拼凑方案数
	private static HashMap<Long,Long> mem = new HashMap<Long,Long>();
	
	static {
		mem.put(-1L,0L);
		mem.put(0L,1L);
		mem.put(1L,1L);
	}
	
	private static long n=0;//面值

	/**
	 * 以2为底n的对数
	 */
	private static long log2(long n) {
		return (long) (Math.log(n) / Math.log(2));
	}

	/**
	 * 获得面值n的拼凑方案数
	 * @param args
	 * @return 
	 */
	private static long getNum(long n) {
//低效		if(n<0) return 0;//面值为负代表剩余硬币的面值不够拼凑新的组合,方案数返回0。
//低效		if(n<mem.size())return mem.get((int)n);
		if(mem.containsKey(n))return mem.get(n);
		else {
			long k=log2(n);//求出题意中2的指数k
			long result=getNum(n-(long )Math.pow(2, k))+getNum((long)Math.pow(2, k+1)-2-n);
			 mem.put(n,result);//记忆已经求过的值(将每一次求过的值存到索引里头,即要递归)
			return result;
		}
		
	}
	public static void main(String[] args) {
		Scanner s=new Scanner(System.in);
		n=s.nextLong();
		long start=System.currentTimeMillis();
		System.out.println(getNum(n));
		System.out.println("用时为:["+(System.currentTimeMillis()-start)+"]");
	
	}
}

最大收益

import java.util.ArrayList;
import java.util.Collections;

public class 最大收益 {

	/**
	 * 最大收益
	 * 
	 * @param index
	 * @param income
	 * @param prev
	 * @return
	 */
	// private static int maxIncome(int index, int[] income, int[] prev) {
	// if (index == 0) {
	// return income[0];
	// }
	// if (prev[index] == -1) {
	// return Math.max(income[index], maxIncome(index - 1, income, prev));
	// } else {
	// return Math.max(income[index] + maxIncome(prev[index], income, prev),
	// maxIncome(index - 1, income, prev));
	// }
	// }
	//
	// public static void main(String[] args) {//递归
	// int[] income = { 5, 1, 8, 4, 6, 3, 2, 4 };// 任务收益
	// int[] prev = { -1, -1, -1, 0, -1, 1, 2, 4 };
	// // 保存第索引位的任务之前能做的任务的索引
	//
	// System.out.println(maxIncome(7, income, prev));
	// }
	// }

	/**
	 * 自底向上实现最大收益
	 */
	private static int maxIncome(int[] income, int[] prev) {
		ArrayList<Integer> result = new ArrayList<Integer>();
		result.add(income[0]);
		for (int i = 1; i < income.length; i++) {
			if (prev[i] == -1) {
				result.add(Math.max(income[i] + 0, result.get(i - 1)));
			} else {
				result.add(Math.max(income[i] + result.get(prev[i]), result.get(i - 1)));
			}
		}
		return Collections.max(result);
	}

	public static void main(String[] args) {// 递归
		int[] income = { 5, 1, 8, 4, 6, 3, 2, 4 };// 任务收益
		int[] prev = { -1, -1, -1, 0, -1, 1, 2, 4 };
		// 保存第索引位的任务之前能做的任务的索引

		// System.out.println(maxIncome(7, income, prev));
		System.out.println(maxIncome(income, prev));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_临渔_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值