标签
拓扑排序好题 OR 动态规划佳题
题目描述
在一个地图上有 N ( N ≤ 20 ) N\ (N \le 20) N (N≤20) 个地窖,每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。
AC艰难历程
-
0
0
0 分:暴搜 DFS……
- 错误原因:自从我建立 DFS 函数时我的思路就与正解分道扬镳……^_^
-
0
0
0 分:回炉重造了一遍 DP,然后……
- 错误原因:输入不知道被谁改了: (
- 100 100 100 分:当我的输入正确了……
题解
思路
考虑 Dp i \text{Dp}_{\text{i}} Dpi 为以 i \text i i 为结尾的最多拆弹数。
推出方程:
Dp i = max { Dp son } + a i \text{Dp}_{\text{i}} = \max\{\text{Dp}_{\text{son}}\}+\text{a}_{\text{i}} Dpi=max{Dpson}+ai
循环求解即可
证明
略
代码
#include <bits/stdc++.h>
#define ios \
ios::sync_with_stdio(0); \
cin.tie(0); \
cout.tie(0)
// #pragma GCC Typetimize(2)
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define il inline
#define p_q priority_queue
#define u_m unordered_map
#define r_g register
using namespace std;
namespace Nothing {
il int read() {
int f = 1, t = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
if ( ch == '-' ) {
f = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
t = t * 10 + ch - '0';
ch = getchar();
}
return t * f;
}
il void write(int x, bool s) {
if (x < 0) {
putchar('-');
write(-x, false);
return ;
}
if (!s && x == 0)
return ;
if (s && x == 0) {
putchar('0');
return ;
}
write(x / 10, false);
putchar(x % 10 + '0');
}
}
int n;
int val[205];
int G[205][205];
int Dp[205];
int ans = 0;
int Lst[205];
int Nct[205];
void Put(int t) {
if (t) {
Put(Lst[t]);
cout << (Lst[t] ? "-" : "") << t;
}
}
signed main() {
ios;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> val[i];
}
int x, y;
while (cin >> x >> y) {
G[x][y] = 1;
}
int Last = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (G[j][i] == 0) continue;
if (Dp[j] > Dp[i]) {
Dp[i] = Dp[j];
Lst[i] = j;
Nct[j] = i;
}
}
Dp[i] += val[i];
if (Dp[i] > ans) {
ans = Dp[i];
Last = max(Last, i);
}
}
Put(Last);
cout << endl;
cout << ans;
return 0;
}