动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。将复杂的问题分解成多个小问题,以空间换时间,将每个小问题的解保存下来,根据小问题的解来计算复杂的问题。本文提供了动态规划经典问题金矿问题的实现源码。
import java.util.*;
/**
* 金矿挖掘问题,指定金矿需要矿工数量、金矿价值和矿工数
* 目的:获取最大的价值,类似01背包
* @author 殇雪话诀别
*
*/
/*
* 测试数据
5 17
8 11
4 5
9 13
3 12
7 10
*/
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.println("请输入金矿数量、矿工数量:");
int n=in.nextInt(); //金矿数量
int num=in.nextInt(); //矿工数
int[][] jk=new int[2][n]; //用于存储金矿数量
System.out.println("请输入需要矿工数、价值:");
for(int i=0;i<n;i++) {
jk[0][i]=in.nextInt(); //金矿重量
jk[1][i]=in.nextInt(); //金矿价值
}
int[][] dt=new int[n+1][num+1]; //申请空间用于动态规划
for(int i=1;i<=n;i++) { //表示金矿数量为i是的情况
for(int j=1;j<=num;j++) { //表示当矿工数为j时的情况
if(j<jk[0][i-1]) { //矿工总数<当前金矿所需矿工数
dt[i][j]=dt[i-1][j]; //矿工数不足以开采当前金矿,所以和没有该矿时的情况一样
}else {
/*
* 矿工数足以开采当前金矿,有两种情况,分别为:
* 开采该矿,再用开采后的矿工数去开采没有该矿时的情况
* 不开采该矿
*/
if(jk[1][i-1]+dt[i-1][j-jk[0][i-1]]>dt[i-1][j]) {
dt[i][j]=jk[1][i-1]+dt[i-1][j-jk[0][i-1]]; //开采该矿,再用开采后的矿工数去开采没有该矿时的情况
}else {
dt[i][j]=dt[i-1][j]; //不开采该矿
}
}
}
}
System.out.println("最多可挖掘"+dt[n][num]+"个金矿。");
int s[]=new int[n]; //用于记录哪个金矿最终被开采了
int w=num;
for(int i=n;i>0;i--) {
if(dt[i][w]!=dt[i-1][w]) { //从后往前,如果当前价值和未使用这个金矿时的价值相等则表示未使用该金矿
s[i-1]=1;
w=w-jk[0][i-1]; //将矿工数减去当前矿需要的矿工数量
}
}
for(int i=0;i<n;i++) {
if(s[i]!=0) {
System.out.println("第"+(i+1)+"个金矿,重量:"+jk[0][i]+",价值:"+jk[1][i]+"。");
}
}
}
}