算法第3章作业
1.
动态规划所处理的问题是一个多阶段决策问题,一般由初始状态开始,通过对中间阶段决策的选择,达到结束状态。这些决策形成了一个决策序列,同时确定了完成整个过程的一条活动路线(通常是求最优的活动路线)。如图所示。动态规划的设计都有着一定的模式,一般要经历以下几个步骤。
┌───┐┌───┐┌───┐
初始状态→│决策1│→│决策2│→…→│决策n│→结束状态
└───┘└───┘└───┘
2. 编程题 (1)
7-1 单调递增最长子序列 (20 分)
设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
思考:首先我考虑假如求A[1],A[2],…,A[i]的最长非降子序列的长度,其中i<N, 那么上面的问题变成了原问题的一个子问题(问题规模变小了,可以让i=1,2,3等来分析) 然后我们定义d(i),表示前i个数中以A[i]结尾的最长非降子序列的长度。可以估计到这个d(i)就是我们要找的状态。 如果我们把d(1)到d(N)都计算出来,那么最终我们要找的答案就是这里面最大的那个。
想要求d(i),就把i前面的各个子序列中, 最后一个数不大于A[i]的序列长度加1,然后取出最大的长度即为d(i)。 当然,有可能i前面的各个子序列中最后一个数都大于A[i],那么d(i)=1, 即它自身成为一个长度为1的子序列。
方法实现:
int lis(int A[], int n){ int *d = new int[n]; int len = 1; for(int i=0; i<n; ++i){ d[i] = 1; for(int j=0; j<i; ++j) if(A[j]<=A[i] && d[j]+1>d[i])//找到最后一个小于i且满足递增序列的那个数 d[i] = d[j] + 1;//找到后那个书的最长序列加一 if(d[i]>len) len = d[i];//若找到 ,将新的序列长度赋值给len } delete[] d; return len; }
编程题(2)
7-2 租用游艇问题
思考:动态规划:
定义f[i][j]为站点i到站点j的最少租金:
rent[i][j] = min { rent[i][k] + rent[k][j] }
其中 i<k<j, 0<=i,j<=n-1
则最少租金为 rent[0][n-1]
方法实现:
#include<iostream> using namespace std; int rent[1000][1000]; int A(int n){ int t; for(int i=n-2; i>=1; i--){ for(int j=i+2; j<=n; j++){ for(int k=i+1; k<j; k++){ t = rent[i][k] + rent[k][j]; if(t<rent[i][j]){ rent[i][j] = t; } } } } return rent[1][n]; } int main(){ int n; cin>>n; for(int i=1; i<n; i++){ for(int j=i+1; j<=n; j++){ cin>>rent[i][j]; /*输入格式:1->2, 1->3 2->3 */ } } cout<<A(n); }
3.结对编程思考
最近与同伴共同编程时间较少,虽有线上交流,但缺少更多线下的讨论和合作。以后需注意。