写的过程十分煎熬,实在是不会写,还要继续熟悉啥是背包。。。。
动态规划最难的不是转移方程,而是设计dp的含义啊
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn = 200 + 11;
typedef long long ll;
ll f[110][110][110], g[110][110][110];
int k, n, m;
ll sum[110], dis[maxn];
struct Node {
int p;
int len;
Node(int a, int b) :p(a), len(b) {}
};
vector<Node>G[maxn];
void add(int be, int en, int len) {
G[be].push_back(Node(en, len));
}
int s[maxn];
int cnt = 0;
int dfs(int x, int fa, ll d) {
s[cnt++] = x;
dis[x] = d;
for (int i = 0; i < G[x].size(); i++) {
int p = G[x][i].p;
ll ln = G[x][i].len;
if (p == fa) continue;
dfs(p, x, d + ln);
for (int b = 0; b < cnt; b++) {
int ff = s[b];
for (int j = k; j >= 0; j--) {
f[x][ff][j] += f[p][ff][0];
g[x][ff][j] += f[p][x][0];
for (int a = 0; a <= j; a++) {//01背包
f[x][ff][j] = min(f[x][ff][j], f[x][ff][j - a] + f[p][ff][a]);
g[x][ff][j] = min(g[x][ff][j], g[x][ff][j - a] + f[p][x][a]);
}
}
}
}
//补齐x--->ff的流量
for (int i = 0; i < cnt; i++) {
int ff = s[i];
for (int j = 0; j <= k; j++) {
if (j == 0) {
f[x][ff][j] += sum[x] * (dis[x] - dis[ff]);
}
else {
//判断是否让x成为工厂
f[x][ff][j] = min(f[x][ff][j] + sum[x] * (dis[x] - dis[ff]), g[x][ff][j - 1]);
}
}
}
cnt--;
return 0;
}
int main() {
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++) {
int be = i, en, len;
scanf("%lld %d %d", &sum[i], &en, &len);
add(be, en, len);
add(en, be, len);
}
cnt = 0;
dfs(0, -1, 0);
printf("%lld
", f[0][0][k]);
return 0;
}