第三章作业-动态规划
在一个地图上有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
//
设nums[i]为第i个地窖埋的地雷数
count[i]为选择第i个地窖挖时的最大地雷数,则
count[i] = max{nums[i] + count[j] | 地窖i、j相连} i<j<=n
path[i]记录挖完第i个地窖后,下一个菜窖选择哪一个挖的地雷数最多。
//
#include <iostream>
using namespace std;
const int MAX = 210;
int conn[MAX][MAX] = {0}; //记录两个菜窖是否联通
int count[MAX] = {0}; //挖到第i个地窖时的最大地雷数
int path[MAX] = {0}; //记录挖地雷的最优路径
int main() {
int n;
cin >> n;
int nums[n];
for (int i = 1; i <= n; i++)
cin >> nums[i];
while (true) {
int a, b;
cin >> a >> b;
if (a == 0 && b == 0) break;
conn[a][b] = 1;
}
//从右至左依次填表
for (int i = n; i >= 1; i--) {
count[i] = nums[i];
for (int j = i + 1; j <= n; j++) {
if (conn[i][j] == 1) {
int tmp = nums[i] + count[j];
if (tmp > count[i]) {
count[i] = tmp;
path[i] = j;
}
}
}
}
//比较从哪个菜窖开始挖地雷数最多
int max = 0; //挖到最多的地雷数
int id = 1; //从哪个菜窖开始挖
for (int i = 1; i <= n; i++) {
if (count[i] > max) {
max = count[i];
id = i;
}
}
//输出挖地雷路径
cout << id;
while (path[id] > 0) { //path[i]为0时,表示无连接,路径结束
cout << "-" << path[id];
id = path[id];
}
cout << endl << max << endl;
}
#
时间复杂度为0(n^2),空间复杂度为0(n^2)
#对动态规划法的理解
动态规划思想与分治法类似,都是将问题分解为多个子问题,通过求解子问题来得到最终答案,而动态规划的优势在于,动态规划防止了子问题的重复计算,每个问题只计算一次,自底向上地求出原问题的解。
#结对编程
我的队友是林晓钿和刘思彤;本次编程我们先各自独立编程,编程完成或是遇见困难后,再交流各自的思路并尝试优化对方的算法。然后接着我们互相讨论了互相的代码,最后统一了理解。