算法第三章作业
1. 任选作业题”单调递增最长子序列“、”挖地雷“、”编辑距离问题“中的一题分析。
——————我选“挖地雷”拼题如下:
3-3 挖地雷 (25分)
在一个地图上有n个地窖(n≤200),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径,并规定路径都是单向的,且保证都是小序号地窖指向大序号地窖,也不存在可以从一个地窖出发经过若干地窖后又回到原来地窖的路径。某人可以从任意一处开始挖地雷,然后沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使他能挖到最多的地雷。
输入格式:
第一行:地窖的个数;
第二行:为依次每个地窖地雷的个数;
下面若干行:
xi yi //表示从xi可到yi,xi<yi。
最后一行为"0 0"表示结束。
输出格式:
k1-k2−…−kv //挖地雷的顺序 挖到最多的雷。
输入样例:
6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0
输出样例:
3-4-5-6
34
1 #include<iostream> 2 #define N 210 3 using namespace std; 4 int b[N][N]; 5 int w[N],p[N]; 6 int f[N];// 表示挖到地雷最大数 7 void print(int k) //输出挖地雷的顺序 8 { 9 if(k == 0) 10 return; 11 print(p[k]); 12 if(p[k] == 0)//如果是第一个点 直接输出k 否则输出-k 13 cout << k; 14 else 15 cout << "-" << k; //否则输出-k 16 } 17 int main(){ 18 int n; 19 cin >> n; 20 for(int i = 1; i <= n; i++) 21 { 22 cin >> w[i]; //输入 23 f[i] = w[i]; 24 } 25 int x,y; 26 while(cin>>x>>y){ 27 if(x==0) 28 break; 29 b[x][y] = 1;//标识x->y通路 30 } 31 int k ,maxx = 0; 32 for(int i = 1; i <= n;i++) 33 { 34 for(int j = 1; j < i;j++) 35 { 36 if(b[j][i] == 1 && f[j]+w[i] > f[i])//j可以到i 且 f[j]+w[i] > f[i] 37 { 38 f[i] = f[j] + w[i];//保存第i个地窖起挖到的后继最大地雷数 39 p[i] = j; //j 地窖是i的最优路径 40 } 41 } 42 if(f[i] > maxx)//计算挖到最多地雷数 43 { 44 maxx = f[i]; 45 k = i; 46 } 47 } 48 print(k); 49 cout <<endl <<maxx <<endl; 50 return 0; 51 }
1.1根据优子结构性质,列出递归方程式:
设w[i]为第i个地窖所藏地雷数。f[i]表示从第i个地窖开始最多可以挖出地雷数
f[i] = max{w[i] + f[j]} (a[i][j] > 0, i< j <= n)
1.2 给出填表法中表的维度、填表范围和填表顺序。
边界f[i]=w[i],
表的维度:一维 (f[n])
填表范围:[1,n]
填表顺序:递增,1~n
1.3 分析该算法的时间和空间复杂度
时间复杂度O(n^2)
空间复杂度O(n)
2. 你对动态规划算法的理解
主要是清楚最优子结构的含义、分析出重叠子问题。
可以采取自顶向下(备忘录方法)或者自底向上(DP算法)的填表方式。
还有一点很重要,特别处理填表时侯的 边界问题。
所谓边界问题,就像递归中的基例。在填表的时候的”最初的起点“
3. 说明结对编程情况
结对编程老好玩了,一头激昂代码,一头指点江山。
debug也快。
做题也快。
别人笑我真君子,我笑他人假骗子