P3354 [IOI2005]Riv 河流
写的过程十分煎熬,实在是不会写,还要继续熟悉啥是背包。。。。
动态规划最难的不是转移方程,而是设计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\n", f[0][0][k]); return 0; }
寻找真正的热爱