动态规划
对动态规划的理解
多态规划是通过将一个大的问题分为多个子问题,并且将子问题再进行划分,一直到求得每个子问题的最优解,
在这个过程中登记子问题的解,不进行子问题的重复计算,大大提升了计算速度。
动态规划分为很种类型的问题,一个问题能否看成一个动态规划的问题,主要看它是否存在
这重复子问题以及最优子结构。
例题
7-1 单调递增最长子序列 (20 分)
设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
输入格式:
输入有两行: 第一行:n,代表要输入的数列的个数 第二行:n个数,数字之间用空格格开
输出格式:
最长单调递增子序列的长度
输入样例:
在这里给出一组输入。例如:
5
1 3 5 2 9
输出样例:
在这里给出相应的输出。例如:
4
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int *a,*count; 6 int n; 7 cin>>n; 8 a=new int [n]; 9 count=new int [n]; 10 for(int i=0;i<n;i++) 11 { 12 count[i]=1; 13 } 14 for(int i=0;i<n;i++) 15 { 16 cin>>a[i]; 17 } 18 for(int i=0;i<n;i++) 19 { 20 int k=i+1; 21 for(int j=i;j<n-1;) 22 { 23 if(a[j]<a[k]) 24 { 25 count[i]++; 26 j=k; 27 k++; 28 } 29 else 30 { 31 k++; 32 } 33 } 34 } 35 int max=count[0]; 36 for(int i=1;i<n;i++) 37 { 38 if(max<count[i]) 39 { 40 max=count[i]; 41 } 42 } 43 cout<<max<<endl; 44 return 0; 45 }
思想:
设置一个 k 下标,定位移动,当前者小于后者的时候,将k赋值给j,
否则就将j定位在当前的 k 的位置,而 k 持续下移,知道出现一个比 j 定位的地方大的数字
7-2 租用游艇问题 (17 分)
题目来源:王晓东,《算法设计与分析》
长江游艇俱乐部在长江上设置了n个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。游艇出租站i到游艇出租站j之间的租金为r(i,j),1<=i<j<=n。试设计一个算法,计算出从游艇出租站1 到游艇出租站n所需的最少租金。
输入格式:
第1 行中有1 个正整数n(n<=200),表示有n个游艇出租站。接下来的第1到第n-1 行,第i行表示第i站到第i+1站,第i+2站, ... , 第n站的租金。
输出格式:
输出从游艇出租站1 到游艇出租站n所需的最少租金。
输入样例:
在这里给出一组输入。例如:
3
5 15
7
输出样例:
在这里给出相应的输出。例如:
12
1 #include <iostream> 2 using namespace std; 3 int main() 4 { 5 int n; 6 cin>>n; 7 int *A[n+1]; 8 for(int i=0;i<=n;i++) 9 { 10 A[i]=new int [n+1]; 11 } 12 for(int i=1;i<=n;i++) 13 { 14 A[i][i]=0; 15 } 16 for(int i=1;i<n;i++) 17 { 18 for(int j=i+1;j<=n;j++) 19 { 20 cin>>A[i][j]; 21 } 22 } 23 24 for(int i=2; i<=n; i++){ 25 for(int j=i+1; j<=n; j++){ 26 int k=j-i; 27 for(int p=k;p<j;p++) 28 if(A[k][p]+A[p][j]<A[k][j])//取最小 29 A[k][j]=A[k][p]+A[p][j]; 30 } 31 } 32 cout<<A[1][n]<<endl; 33 return 0; 34 }
思想:弃用0下标,
这是一个动态规划问题,从左往右,从下往上添加矩阵,在此处选用了斜对角线添加的方式,矩阵中的每个点都选出它最小的价格填进去,知道最后A【1】【n】就是全程的一个最优值。
结对编程的情况:两个人之间相辅相成,在解题过程中有着不可或缺的作用、