算法导论15章动态规划

钢条切割问题

public class Main {
	int n = 10;
	int[] p = new int[]{1,5,8,9,10,17,17,20,24,30};
	int[] r = new int[n+1];
	int[] s = new int[n+1];
	
	int solve(int n,int[] s,int c){
		if(n==0) return 0;
		if(r[n]>=0) return r[n];
		else{
			int max = -10000;
			for(int i=1;i<=n;i++){
				int t = p[i-1]+solve(n-i,s,c)-c;
				if(t>max){
					max = t;
					s[n] = i;
				}				
			}
			r[n] = max;
			return max;
		}
	}
	
	void solve2(int n){
		Arrays.fill(r, -1);
		r[0] = 0;
		for(int i=1;i<=n;i++){
			int max = 0;
			for(int j=1;j<=i;j++){
				if(max<p[j-1]+r[i-j]){
					max = p[j-1]+r[i-j];
					s[i] = j;
				}
			}
			r[i] = max;
		}
		System.out.println("最大价值为"+r[n]);
		System.out.println("切割方式:");
		while(n>0){
			System.out.println(s[n]);
			n = n-s[n];
		}
	}
	
	public static void main(String[] args) {
		Main m = new Main();	
		Arrays.fill(m.r, -1);
		System.out.println(m.solve(7,m.s,1));
		System.out.println(Arrays.toString(m.s));
		int n = 7;
		while(n>0){
			System.out.println(m.s[n]);
			n = n-m.s[n];
		}
	}
}

矩阵链乘

public class Main {
	int n = 6;
	int[][] m = new int[n][n];
	int[][] s = new int[n][n];
	int solve(int[] p){
		for(int i=0;i<n;i++){
			m[i][i] = 0;
		}
		for(int l=1;l<n;l++){//l-1为几个矩阵相乘
			for(int i=0;i<n-l;i++){//i为起始
				int j = i+l;//j为结束
				m[i][j] = 100000;
				for(int k=i;k<j;k++){//k为分割点
					if(m[i][j]>m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1]){
						m[i][j]=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];
						s[i][j] = k;
					}
				}
			}
		}
		
		return m[0][n-1];
	}
	
	int solve(int[] p,int i,int j){
		if(m[i][j]>0) return m[i][j];
		if(i==j) return 0;
		m[i][j] = 100000;
		for(int k=i;k<j;k++){
			int t = solve(p, i, k)+solve(p,k+1,j)+p[i]*p[k+1]*p[j+1];
			if(m[i][j]>t){
				m[i][j] = t;
				s[i][j] = k;
			}
		}
		return m[i][j];
	}
	
	void print(int[][] s,int i,int j){
		if(i==j){
			System.out.print("A"+i);
		}else{
			System.out.print('(');
			print(s, i, s[i][j]);
			print(s, s[i][j]+1,j);
			System.out.print(')');
		}
	}
	
	public static void main(String[] args) {
		Main m = new Main();	
		//System.out.println(m.solve(new int[]{5,10,3,12,5,50,6}));
		//m.print(m.s,0,5);
		System.out.println(m.solve(new int[]{5,10,3,12,5,50,6},0,5));
		m.print(m.s,0,5);
	}
}
最长公共子序列

public class Main {	
	
	void solve(char[] x,char[] y){
		int m = x.length;
		int n = y.length;
		int c[][] = new int[m+1][n+1];
		for(int i=0;i<n;i++){
			c[0][i] = 0;
		}
		for(int i=0;i<m;i++){
			c[i][0] = 0;
		}
		for(int i=1;i<=m;i++){//i为子序列长度
			for(int j=1;j<=n;j++){//j为子序列长度
				if(x[i-1]==y[j-1]){
					c[i][j] = c[i-1][j-1]+1;
				}else{
					c[i][j] = Math.max(c[i][j-1], c[i-1][j]);
				}
			}
		}
		System.out.println(c[m][n]);
		print(c, m, n, x);
	}
		
	int solve2(int c[][],char[] x,char[] y,int i,int j){
		if(c[i][j]>0) return c[i][j];
		if(i==0||j==0) c[i][j] = 0;
		else{
			if(x[i-1]==y[j-1]){
				c[i][j] = solve2(c, x, y, i-1, j-1)+1;
			}else{			
				c[i][j] = Math.max(solve2(c, x, y, i-1, j), solve2(c, x, y, i, j-1));
			}
		}
		return c[i][j];
	}
	
	void print(int[][] c,int m,int n,char[] x){		
		if(m==0||n==0) return;
		if(c[m][n]==c[m-1][n-1]+1){
			System.out.println(x[m-1]);
			print(c, m-1, n-1, x);
		}else if(c[m][n]==c[m-1][n]){
			print(c, m-1, n, x);
		}else{
			print(c, m, n-1, x);
		}
	}
	
	public static void main(String[] args) {
		Main m = new Main();	
		//m.solve("BDCABA".toCharArray(),"ABCBDAB".toCharArray());
		char[] a1 = "BDCABA".toCharArray();
		char[] a2 = "ABCBDAB".toCharArray();
		int[][] c = new int[a1.length+1][a2.length+1];		
		int t = m.solve2(c, a1, a2, a1.length, a2.length);
		System.out.println(t);
		m.print(c, a1.length, a2.length, a1);
	}
}

最长单调递增子序列

public class Main {	
	
	void solve(int[] arr){
		int[] d = new int[arr.length];
		d[0] = 1;
		for(int i=0;i<arr.length;i++){
			d[i] = 1;
			for(int j=0;j<i;j++){
				if(arr[i]>arr[j]){
					if(d[j]+1>d[i]){
						d[i] = d[j]+1;
					}
				}
			}
		}
		System.out.println(d[arr.length-1]);
	}
	
	public static void main(String[] args) {
		Main m = new Main();	
		m.solve(new int[]{1,1,2,3,4,1,2,7,5,7,1,3,4,8,9});
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值