动态规划入门例子

我最近才开始学习动态规划,在网上看到一个简单的例子,也是入门级的,大神路过请无视!

这里是我看的文章链接(传送门):http://www.360doc.com/content/13/0601/00/8076359_289597587.shtml


在这,我把入门例子的“如何用最少枚硬币凑够成11元”和求“最长非降子序列的长度”做一遍

“如何用最少枚硬币凑够成11元”:

import java.util.Scanner;

public class MianZhi {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();// 输入需要找零的钱
		sc.close();

		int[] mz = new int[] { 1, 3, 5 };// 拥有的硬币面值
		int[] dp = new int[n + 1];// 一个保存从1元到n元,各自最少需要多少个硬币数目的数组
		// 初始化,假设i元都需要2147483647个硬币
		for (int i = 1; i < dp.length; i++)
			dp[i] = Integer.MAX_VALUE;

		for (int i = 1; i <= n; i++) {
			for (int j = 0; j < mz.length; j++) {
				// 条件1: i >= mz[j]:表示的是,有比i元要小或相等的面值的硬币
				/* 条件2:
				 * dp[i] > dp[i - mz[j]] + 1:表示的是:
				 * 首先,dp[i]:是i元当前是由dp[i]个硬币组成
				 * 然后,dp[i - mz[j]]:表示的是i - mz[j]元需要dp[i - mz[j]]个硬币
				 * 最后,+ 1是因为条件1满足了,说明可以加上一个面值为mz[j]的硬币 
				 * 两个条件都满足的话,那么dp[i - mz[j]] + 1个硬币可以表示i元
				 */
				if (i >= mz[j] && dp[i] > dp[i - mz[j]] + 1)
					dp[i] = dp[i - mz[j]] + 1;
			}
		}

		//输出i元各自最少需要多少个硬币
		for (int i = 1; i < dp.length; i++)
			System.out.print(dp[i] + " ");
	}
}


求“最长非降子序列的长度”

import java.util.Scanner;

public class LIS {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		// 将输入的数字串转成一个字符串数组
		String data[] = sc.nextLine().split(" ");
		sc.close();

		// 将data数组转成int类型的数组
		int[] d = new int[data.length];
		for (int i = 0; i < d.length; i++)
			d[i] = Integer.parseInt(data[i]);

		// 保存LIS的数组
		int[] temp = new int[data.length];
		temp[0] = d[0];// 先去第一个元素给temp[0],那么len自然就是1
		int len = 1;

		/*
		 * 输入例子 5 3 4 8 6 7
		 */

		for (int i = 1; i < temp.length; i++) {

			int left = 0, right = len;
			while (left <= right) {
				int mid = (left + right) >> 1;
				// 二分查找d[i]的插入位置
				if (temp[mid] < d[i])
					left = mid + 1;
				else
					right = mid - 1;
			}
			temp[left] = d[i];
			// 当left大于len了,那么说明有新元素插入,要+1
			len = left > len ? len + 1 : len;
		}

		//输出子序列,0不算
		for (int i = 0; i < temp.length; i++) {
			System.out.print(temp[i] + " ");
		}
		System.out.println("\n" + len);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值