算法第三章作业
1.对动态规划算法的理解
基本思想:
动态规划算法与分治法类似,其基本思想也是将待求解的问题分解成若干个子问题,先求子问题,然后从这些子问题的解得到原问题的解,但是,适合动态规划法求解的问题,经分解得到的子问题往往不是互相独立的。同时也会存在有些子问题被重复计算了很多次,为了避免大量的重复计算,从而得到多项式时间算法,可以用一个表来记录所有已解决的子问题的答案,不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。
基本步骤:
(1)找出最优解的性质,并刻画其结构特征
(2)递归地定义最优解
(3)以自底向上的方式计算出最优解
(4)根据计算最优值时得到的信息,构造最优解。
基本要素:
(1)最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。
(2)重叠子问题:在用递归算法自顶向下解此问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格里,当再次需要解此子问题时,只是简单地用常数时间查看一下结果。
(3)备忘录方法:备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。
2.分别列出编程题1、2的递归方程
7-1 单调递增最长子序列
设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int[] nums = new int[n + 1];// 数列数据
int[] sub_len = new int[n + 1];// sub_len[i]表示从i到n的最长递增序列的长度
int[] sub_index = new int[n + 1];// sub_index[i]表示第i个数据的后面一个数据的下标
for (int i = 1; i <= n; i++) {
nums[i] = scanner.nextInt();
sub_len[i] = 1;
sub_index[i] = 0;
}
for (int i = n - 1; i >= 1; i--) {
int max = 0, p = 0;// 临时变量
for (int j = i + 1; j <= n; j++) {
if (nums[i] < nums[j] && sub_len[j] > max) {
max = sub_len[j];
p = j;
}
if (p != 0) {
sub_len[i] = sub_len[p] + 1;
sub_index[i] = p;
}
}
}
int max = 0, p = 0;
for (int i = 1; i <= n; i++) {
if (sub_len[i] > max) {
max = sub_len[i];
p = i;
}
}
System.out.print(max);
}
}
}
7-2 租用游艇问题
长江游艇俱乐部在长江上设置了n个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i<j<=n。试设计一个算法,计算出从游艇出租站1 到游艇出租站n所需的最少租金。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int dis[][] = new int [100][100];//dis[i][j]表示从第i站到第j站所需的租金
//记录每个站间的租金
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
dis[i][j]= input.nextInt();
}
}
//计算第1站到第j站所需的最少租金
for(int j=2;j<=n;j++){
for(int i=2;i<j;i++){
if(dis[1][j]>dis[1][i]+dis[i][j])
dis[1][j]= dis[1][i]+dis[i][j];
}
}
System.out.print(dis[1][n]);
}
}
3.说明结对编程情况
开始做题的时候,还是不太明白怎么用动态规划来做。后来我和我的两个搭档一起看书,讨论,模仿着书上的例题来做,同时也得到了其他同学的帮助,我们最终还是解决了这些题目,对于动态规划算法也有了进一步的了解。和小伙伴们一起合作讨论比自己埋头苦干要有效的多。
浙公网安备 33010602011771号