您的位置:首页 > 编程语言 > Java开发

《趣学算法》第四章 动态规划代码实现(Java)

2018-01-22 17:24 253 查看

4.3 最长的公共子序列

import java.util.Scanner;

public class Test4_3 {
static String s1;
static String s2;

public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("输入字符串s1:");
s1=scanner.next();
System.out.println("输入字符串s2:");
s2=scanner.next();
int len1=s1.length();                          //计算两个字符串的长度
int len2=s2.length();

int[][] c=new int[len1+1][len2+1];             //存放公共子序列的最大长度
int[][] b=new int[len1+1][len2+1];             //记录来源

for(int i=0;i<=len1;i++)
c[i][0]=0;                                 //初始化第一列为0
for(int j=0;j<=len2;j++)
c[0][j]=0;                                 //初始化第一行为0

LCSL(c,b);                                     //求解最长公共子序列
System.out.println("s1和s2的最长公共子序列长度是:"+c[len1][len2]);
System.out.print("s1和s2的最长公共子序列是:");
print(len1,len2,b);                            //递归构造最长公共子序列最优解
}

/*求解最长公共子序列*/
public static void L
4000
CSL(int[][] c,int[][] b) {
int i,j;
for(i=1;i<=c.length-1;i++) {                   //控制s1的序列,即遍历s1的每个字符
for(j=1;j<=c[i].length-1;j++) {            //控制s2的序列,即用s1的字符与s2的所有字符进行比较

if(s1.charAt(i-1)==s2.charAt(j-1)) {   //字符下标从0开始
//如果当前字符相同,则公共子序列的长度为该字符前的最长公共序列+1
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}
else {
if(c[i][j-1]>=c[i-1][j]) {         //找出两者最大值,若相等默认取左侧
c[i][j]=c[i][j-1];             //取左侧值
b[i][j]=2;
}
else {
c[i][j]=c[i-1][j];             //取上面值
b[i][j]=3;
}
}
}
}
}

/*递归构造最长公共子序列最优解*/
public static void print(int i,int j,int[][] b) {
if(i==0||j==0)
return;                                    //递归结束条件
if(b[i][j]==1) {                               //来源左上角
print(i-1,j-1,b);
System.out.print(s1.charAt(i-1));
}
else if(b[i][j]==2)
print(i,j-1,b);                            //来源左侧
else
print(i-1,j,b);                            //来源上面
}
}


程序运行结果如下:



4.4 编辑距离

import java.util.Scanner;

public class Test4_4 {

public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("输入字符串str1:");
String str1=scanner.next();
System.out.println("输入字符串str2:");
String str2=scanner.next();
int answer=editDistance(str1,str2);                  //求编辑距离
System.out.println(str1+"和"+str2+"的编辑距离是:"+answer);
}

public static int editDistance(String str1,String str2) {
int len1=str1.length();                              //计算字符串的长度
int len2=str2.length();
int[][] d=new int[len1+1][len2+1];                   //d[i][j]表示str1前i个字符和str2前j个字符的编辑距离

for(int i=0;i<=len1;i++)                             //当第二个字符串长度为0时,编辑距离初始化为i
d[i][0]=i;
for(int j=0;j<=len2;j++)                             //当第一个字符串长度为0时,编辑距离初始化为j
d[0][j]=j;

for(int i=1;i<d.length;i++) {                        //遍历str1的每个字符
for(int j=1;j<d[i].length;j++) {                 //与第二个字符串的每个字符进行比较
int diff;                                    //判断str1[i]是否等于str2[j],相等为0
if(str1.charAt(i-1)==str2.charAt(j-1)) {     //字符串小标从0开始
diff=0;
}
else
diff=1;

int temp=Math.min(d[i-1][j]+1, d[i][j-1]+1);  //去三者中最小值
d[i][j]=Math.min(temp,d[i-1][j-1]+diff);
}
}
return d[len1][len2];
}

}


程序运行结果如下:



4.5 游艇租赁

import java.util.Scanner;

public class Test4_5 {
static int n;
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入站点的个数n:");
n=scanner.nextInt();
System.out.println("请依次输入各站点之间的租金:");
int[][] r=new int[n+1][n+1];                            //存放各站点之间的租金
int[][] m=new int[n+1][n+1];                            //各个子问题的最优值
int[][] s=new int[n+1][n+1];                            //各个子问题的最优决策
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++) {
r[i][j]=scanner.nextInt();
m[i][j]=r[i][j];                                //初始化m数组
}
}
rent(m,s);                                              //求最少租金
System.out.println("花费最少的租金为:"+m[1]
);
System.out.print("最少租金经过的站点:1");
print(1,n,s);
System.out.println();
scanner.close();
}

/*最少租金求解函数*/
public static void rent(int[][] m,int[][] s) {
int i,j,k,d;
for(d=3;d<=n;d++) {                                     //将问题划分为小规模d,3个站点、4个站点...n个站点
for(i=1;i<=n-d+1;i++) {                             //子问题的初始站点
j=i+d-1;                                        //子问题的终点站点
for(k=i+1;k<j;k++) {                            //可停靠站点
int temp=m[i][k]+m[k][j];                   //在站点k停留
if(temp<m[i][j]) {                          //停留后的租金和比直达的租金便宜
m[i][j]=temp;
s[i][j]=k;                              //记录停靠点
}
}
}
}
}

/*求得停靠点,当s[i][j]=0时说明中间没有停靠点,输出站点j,否则划分为两个子问题*/
public static void print(int i,int j,int[][] s) {
if(s[i][j]==0) {
System.out.print("——"+j);
return;
}
print(i,s[i][j],s);
print(s[i][j],j,s);
}
}


程序运行结果如下:



4.6 矩阵连乘

import java.util.Scanner;

public class Test4_6 {
static int n;
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入矩阵的个数n:");
n=scanner.nextInt();
int[] p=new int[n+1];                          //记录矩阵行列
int[][] m=new int[n+1][n+1];                   //最优值数组
int[][] s=new int[n+1][n+1];                   //最优决策数组

System.out.println("请依次输入每个矩阵的行数和最后一个矩阵的列数:");
for(int i=0;i<=n;i++)
p[i]=scanner.nextInt();
matrixChain(p,m,s);                            //矩阵连乘求解函数
print(1,n,s);
System.out.println();
System.out.println("最小计算量的值为:"+m[1]
);
}

/*矩阵连乘求解函数*/
public
bd17
static void matrixChain(int[] p,int[][] m,int[][] s) {
int i,j,r,k;
for(r=2;r<=n;r++) {                            //2个矩阵连乘、3个矩阵连乘...n个矩阵连乘
for(i=1;i<=n-r+1;i++) {                    //r个矩阵开始矩阵的下标
j=i+r-1;                               //结束矩阵
m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];    //k=i时的乘法次数
s[i][j]=i;                             //子问题的最优策略是i

for(k=i+1;k<j;k++) {                   //对从i到j的所有策略求最优值
int temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(temp<m[i][j]) {
m[i][j]=temp;
s[i][j]=k;
}
}
}
}
}

/*最优解输出函数*/
public static void print(int i,int j,int[][] s) {
if(i==j) {
System.out.print("A"+i);
return;
}
System.out.print("(");
print(i,s[i][j],s);
print(s[i][j]+1,j,s);
System.out.print(")");
}
}


程序运行结果如下:



4.9 0-1背包问题

import java.util.Scanner;

public class Test4_9 {

public static void main(String[] args) {
int n,W;                                                    //n表示n个物品,W表示购物车容量
Scanner scanner=new Scanner(System.in);
System.out.println("请输入物品的个数n:");
n=scanner.nextInt();
System.out.println("请输入购物车的容量W:");
W=scanner.nextInt();

int[] w=new int[n+1];                                       //存放所有物品的重量
int[] v=new int[n+1];                                       //存放所有物品的价值
int[][] c=new int[n+1][W+1];                                //表示前i个物品放入容量为j的购物车获得的最大价值

System.out.println("请依次输入每个物品的重量w和价值v,用空格分开:");
for(int i=1;i<=n;i++) {
w[i]=scanner.nextInt();
v[i]=scanner.nextInt();
}

//计算c[i][j]
for(int i=1;i<=n;i++) {                                     //控制物品个数
for(int j=1;j<=W;j++) {                                 //控制容量大小
if(w[i]>j)                                          //物品重量大于购物车容量,则不放入第i个物品
c[i][j]=c[i-1][j];
else
c[i][j]=Math.max(c[i-1][j],c[i-1][j-w[i]]+v[i]);//比较放入此物品与不放入此物品哪个价值更大
}
}
System.out.println("装入购物车的最大价值为:"+c
[W]);

//逆向构造最优解
int[] x=new int[n+1];                                       //表示第i个物品是否放入购物车
int j=W;
for(int i=n;i>0;i--) {                                      //从最后一个物品开始判断
if(c[i][j]>c[i-1][j]) {                                 //说明第i个物品放入购物车
x[i]=1;
j-=w[i];
}
else
x[i]=0;                                             //说明第i个物品没有放入购物车
}
System.out.println("装入购物车的物品为:");
for(int i=1;i<=n;i++) {
if(x[i]==1)
System.out.print(i+"  ");
}
}
}


程序运行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: