实验2 动态规划
学号:6130116217
专业班级:计算机科学与技术165班
课程名称:算法分析与设计实验
一、最长不下降子序列问题
1、分析
- 此题为课本中6.2.1节的最长非降子序列问题。
- 我用递推的dtgh(dp)完成该程序。
- 思路是:随机生成n个1000以内的数,并用数组int a[]记录,dp[i]表示已a[i]结尾的最长非降子序列长度。
- 当①:a[i]之前存在a[j],使a[j]<=a[i],有dp[i] = Math.max(dp[i], dp[j] + 1)。
②:a[i]之前不存在a[j],使a[j]<=a[i],则a[i]=1。 - 故有
边界:dp[i]=1,i~[1,n]
状态转移方程:dp[i] = Math.max(dp[i], dp[j] + 1)
最后再通过dp[]反向推导出最长不下降子序列,用堆栈保存,正序输出。
2、代码
package 实验5动态规划;
import java.util.*;
public class 最长非降子序列2 {
static Scanner in = new Scanner(System.in);
static int n;// 序列长度
static int max;// 最大非降子序列长度
static int[] a = new int[1000009];// 存储数组
static int[] dp = new int[1000009];// dp[i]表以i结尾最大非降子序列长度
static Random random = new Random();
static Stack<Integer> stack = new Stack<Integer>();// 存储序列
public static void main(String[] args) {
long time = System.currentTimeMillis();
System.out.println("input n(n<=2000): ");
n = in.nextInt();
for (int i = 1; i <= n; ++i) {
a[i] = (int) (1 + Math.random() * (999));
// a[i] = 1 + random.nextInt(1000);
System.out.print(a[i] + " ");
}
System.out.println();
// 初始化边界
Arrays.fill(dp, 1);
// 状态转移方程
for (int i = 2; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
if (a[i] >= a[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
if (dp[i] > dp[max])
max = i;
}
}
}
System.out.println("L= " + dp[max]);
int p = max;
// 逆序获得序列,入栈
for (int i = dp[max]; i >= 1; --i) {
while (dp[p] != i)
p--;
stack.push(a[p]);
}
System.out.println("其中一个长度为" + dp[max] + "的非降子序列: ");
// 正序输出序列
while (!stack.empty())
System.out.print(stack.pop() + " ");
System.out.println("\n" + (System.currentTimeMillis() - time) + "ms");
}
}
3、测试
- 下面为3组运行结果及其截图
(1)测试结果:
序号 | 序列长度n | 运行时间(ms) |
---|---|---|
1 | 1000 | 2508 |
2 | 10000 | 5244 |
3 | 100000 | 22295 |
4 | 500000 | (长时间无结果) |
可以看出第4次测试长时间计算不出结果。
(2)截图:
n=1000
n=10000
n=100000
3、结论
- 容易看出:dp法解决最长非降子序列问题拥有很好的时空复杂度。同时通过测试数据可以知道,我的程序在第4次测试就已经长时间算不出结果,所以它只能承受n为10^5的数据范围。
二、最长公共子序列问题
1、分析
- 此题为课本中6.2.2节的最长公共子序列问题。
- 思路是:数组s[i][j]当x[i]==y[j]时,s[i][j]=1;当x[i]!=y[j]时,s[i][j]=0.x序列的每一项与y序列的每一项逐一比较,根据s[i][j]与c[i][j]的取值具体构造最长公共子序列。t从0开始取值,当确定最长公共子序列一项时,t=j+1,这样处理可以去重。
- 从文件中读取数据,文件内容列出在测试部分。
2、代码
package 实验5动态规划;
import java.io.*;
import java.util.*;
public class 最长公共子序列 {
static Scanner in = new Scanner(System.in);
static int N = 10000;
static char[] x = new char[N];// 存储串
static char[] y = new char[N];
static String a, b;
static int m, n;// 串x,y的长度
static int t, w;
static int[][] c = new int[N][N];
static int[][] s = new int[N][N];
public static void main(String[] args) throws FileNotFoundException {
long time = System.currentTimeMillis();
Scanner in = new Scanner(new File("src/实验5动态规划/2.txt"));
a = in.next();
b = in.next();
System.out.println("序列x:"); // 先后输入序列
System.out.println(a);
x = a.toCharArray();
System.out.println("序列y:");
System.out.println(b);
y = b.toCharArray();
m = x.length;// 串的长度
n = y.length;
for (int i = 0; i <= m; i++)
c[i][n] = 0; // 赋边界值
for (int j = 0; j <= n; j++)
c[m][j] = 0;
for (int i = m - 1; i >= 0; i--) // 递推计算最优值
for (int j = n - 1; j >= 0; j--)
if (x[i] == y[j]) {
c[i][j] = c[i + 1][j + 1] + 1;
s[i][j] = 1;
} else {
s[i][j] = 0;
if (c[i][j + 1] > c[i + 1][j])
c[i][j] = c[i][j + 1];
else
c[i][j] = c[i + 1][j];
}
System.out.printf("最长公共子序列的长度为:%d", c[0][0]); // 输出最优值
System.out.printf("\n最长公共子序列为:"); // 构造最优解
for (int i = 0; i <= m - 1; i++)
for (int j = t; j <= n - 1; j++)
if (s[i][j] == 1 && c[i][j] == c[0][0] - w) {
System.out.printf("%c", x[i]);
w++;
t = j + 1;
break;
}
System.out.println("\n" + (System.currentTimeMillis() - time) + "ms");
}
}
3、测试
- 下面为3组运行结果及其截图
(1)测试结果:
①:
序列x:hsbafdreghsbacdba
序列y:acdbegshbdrabsa
②:
序列x:hsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdbahsbafdreghsbacdba
序列y:begshbdbegshbdacdbegshbdrabsaacdacdbegshbdrabsaacdacdbegshbdrabsaacdacdbegshbdrabsaacdacdbegshbdrabsaacdacdbegshbdrabsaacdbegshbdrabsaacdbegshbdrabsaacdbegshbdrabsa
③:
序列x:jrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojthbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrik
序列y:kevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrikevrhntiqhbqionvhrioqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeojrgoinoontrjbpwiojtoqinbrqeo