标签:style blog http color io for ar div
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4439
题意:
n个点的有向无环图,边有长度,从一个点到另一点消耗背包重量与边长的乘积。每个点卖物品,价值v,重量w,数量无限,给定起点,和背包容量,可以在任意点停止,问最大化所获得价值的情况下需要消耗的最少能量。
分析:
前两天一拙计没想出来,先放着了,今天水了几次才过= =。f[i][j]表示在i点用j的容量所得最大价值,g[i][j]表示同样状态下获得最大价值所需最小能量,然后拓扑排序,转移即可。因为题是前两天读的,今天想了方程就写,忘记考虑图的连通性,如果不能由起点走到的点就不能用它的答案来更新解。
感想:
前两天卡住主要是突然想不清状态转移。实际上像这题,状态转移可以分开,即同时进行顺推和逆推,循环到i,j的状态时,既是求i,j的状态,也是将i,j的状态转移给所能到的点to,j。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 using namespace std; 6 7 typedef pair<int, int> edge; 8 int n, m, w, x, st; 9 vector<edge> e[610]; 10 long long f[610][2100], g[610][2100]; 11 int c[610], v[610], bfn[610], in[610]; 12 bool reach[610]; 13 int main() 14 { 15 while(scanf("%d %d %d %d", &n, &m, &w, &x) != EOF) 16 { 17 for (int i = 1; i <= n; i++){ 18 scanf("%d %d", c+i, v+i); 19 e[i].clear(); 20 } 21 memset(in, 0, sizeof(in)); 22 int xx, yy, ww; 23 for (int i = 0; i < m; i++) 24 { 25 scanf("%d %d %d", &xx, &yy, &ww); 26 e[xx].push_back(make_pair(yy, ww)); 27 in[yy] ++; 28 } 29 queue<int> q; 30 for (int i = 1; i <= n; i++) 31 if (in[i] == 0) q.push(i); 32 int cnt = 0; 33 while(!q.empty()) 34 { 35 int u = q.front(); q.pop(); 36 bfn[++cnt] = u; 37 if (u == x) st = cnt; 38 for (int i = 0; i < e[u].size(); i++){ 39 int v = e[u][i].first; 40 in[v] --; 41 if (!in[v]) q.push(v); 42 } 43 } 44 memset(reach, false, sizeof(reach)); 45 reach[x] = true; 46 long long ans = 1 << 30, maxv = 0; 47 ans <<= 30; 48 memset(f, 0, sizeof(f)); 49 for (int mark = st; mark <= n; mark++){ 50 int i = bfn[mark]; 51 if (!reach[i]) continue; 52 for (int j = 0; j <= w; j++){ 53 if (j >= c[i]){ 54 long long tmp = f[i][j-c[i]] + v[i]; 55 if (f[i][j] < tmp){ 56 f[i][j] = tmp; 57 g[i][j] = g[i][j-c[i]]; 58 } 59 else if (f[i][j] == tmp){ 60 g[i][j] = min(g[i][j], g[i][j-c[i]]); 61 } 62 } 63 for (int t = 0; t < e[i].size(); t++){ 64 int v = e[i][t].first, l = e[i][t].second; //v肯定还没遍历过 65 reach[v] = true; //f[v][j]暂时表示v点j的容量全由之前点 66 if (f[i][j] > f[v][j]){ //消耗所能获得最大价值 67 f[v][j] = f[i][j]; 68 g[v][j] = g[i][j] + l * j; 69 } 70 else if (f[i][j] == f[v][j]){ 71 g[v][j] = min(g[v][j], g[i][j] + l * j); 72 } 73 } 74 if (f[i][j] > maxv){ 75 maxv = f[i][j]; 76 ans = g[i][j]; 77 } 78 else if (f[i][j] == maxv) ans = min(ans, g[i][j]); 79 } 80 } 81 printf("%lld\n", ans); 82 } 83 return 0; 84 }
ZOJ 3524 Crazy Shopping DAG上的完全背包,布布扣,bubuko.com
ZOJ 3524 Crazy Shopping DAG上的完全背包
标签:style blog http color io for ar div
原文地址:http://www.cnblogs.com/james47/p/3895723.html