动态规划(一)
参考了https://blog.youkuaiyun.com/u013565099/article/details/76610875
收获颇多
动态规划问题关键是找出状态和状态转移条件,但是我还是不熟练qwq
斐波拉契数列
/**
* @Author: TJW
* @Description:
* @Date: 2018/12/7
*/
public class DP_fib {
public static void main(String[] args) {
fib_dp();
}
public static void fib_dp(){
// fib1
//space 30
int[] result = new int[30];
for(int i=0;i<30;i++){
result[i] = -1;
}
result[0] = 1;
result[1] = 1;
//print(result);
System.out.println("fib1:"+fib1(10,result));
//print(result);
//System.out.println("fib1:"+fib1(5,result));
//print(result);
// fib2
System.out.println("fib2:"+fib2(10));
// fib3 uses less space than that fib2 uses
System.out.println("fib3:"+fib3(10));
}
// fib(0-29) top-down, save result
public static int fib1(int n,int[] result){
if(result[n]!=-1){
return result[n];
}else{
result[n] = fib1(n-1,result)+fib1(n-2,result);
return result[n];
}
}
// fib bottom-up
public static int fib2(int n){
if(n<=1){
return 1;
}else{
int temp[] = new int[n+1];
temp[0] = 1;
temp[1] = 1;
for(int i=2;i<n+1;i++){
temp[i]=temp[i-1]+temp[i-2];
}
return temp[n];
}
}
public static int fib3(int n){
if(n<=1){
return 1;
}else{
int temp0 = 1;
int temp1 = 1;
int temp2 = 0;
for(int i=2;i<n+1;i++){
temp2 = temp0+temp1;
temp0 = temp1;
temp1 = temp2;
}
return temp2;
}
}
public static void print(int[] result){
for(int i=0;i<result.length;i++){
System.out.print(result[i]+" ");
}
System.out.println();
}
}
硬币方案
思路:先赋值为只能有1的情况(最多硬币数情况),然后根据可以使用的硬币,将d[i]的指改为d[j+x]=min(d[i],d[j]+1),其中j+x=i,x表示硬币的面额,j表示之前总值为j的情况。
import java.util.Scanner;
/**
* @Author: TJW
* @Description:
* @Date: 2018/12/7
*/
public class DP_coin {
public static void main(String[] args) {
int coins[] = new int[]{1,3,5};
System.out.println("kinds of coins: 1 3 5");
Scanner scanner = new Scanner(System.in);
System.out.println("enter your want num:");
int want = scanner.nextInt();
scanner.close();
int[] minSet = new int[100];
//都使用1的情况
for(int i=0;i<100;i++){
minSet[i] = i;
}
for(int i=0;i<100;i++){
for(int j=0;j<3;j++){
if(coins[j]<i && minSet[i-coins[j]]+1<minSet[i]){
minSet[i] = minSet[i-coins[j]]+1;
}
}
}
System.out.println(minSet[want]);
}
}
最大非减子序列
思路:d[i]是第i个数前可以组成的最大非减子序列,其可以表示为第j个数(小于第i个数)的最大非减子序列+1(如果比现存的值要大)。
/**
* @Author: TJW
* @Description:
* @Date: 2018/12/7
*/
public class DP_LIS {
public static void main(String[] args) {
int[] list = new int[]{5,3,4,8,6,7};
int[] maxLength = new int[list.length];
int len=1;
for(int i=0;i<list.length;i++){
maxLength[i] = 1;
for(int j=0;j<i;j++){
//the most important step
if(list[j]<list[i] && maxLength[j]+1>maxLength[i]){
maxLength[i] = maxLength[j] + 1;
}
if(maxLength[i]>len){
len = maxLength[i];
}
}
}
for(int i=0;i<maxLength.length;i++){
System.out.println(i+1+":"+maxLength[i]);
}
System.out.println(len);
}
}
最多苹果数(从左上角开始,只能向下或向右)
思路:从上到下,依次保存最大苹果数。d[i][j]的数量由上或左所含的最大苹果数量决定。
import java.util.Scanner;
/**
* @Author: TJW
* @Description:
* @Date: 2018/12/7
*/
public class DP_path {
/*max path, only turn down or turn left
1
2 3
4 5 2
1
3 6
7 12 14
*/
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[][] matrix = new int[][]{{1,0,0},{2,3,0},{4,5,2}};
int[][] result = new int[3][3];
for(int i=0;i<3;i++){
for(int j=0;j<=i;j++){
if(j-1>=0 && i-1>=0){
//the most important step
int max_added = Math.max(result[i][j-1],result[i-1][j]);
result[i][j] = max_added+matrix[i][j];
}else if(i-1<0){
result[i][j] = matrix[i][j];
}else if(j-1<0){
result[i][j] = matrix[i][j]+result[i-1][j];
}
}
}
for(int i=0;i<3;i++){
for(int j=0;j<=i;j++){
System.out.print(result[i][j]+" ");
}
System.out.println();
}
}
}