• [IOI2005]Riv 河流


    一道不简单的DP题。我一开始设(f[u][j])表示以u为根的子树中,建立(j)个伐木场的最小运费,并且假定u为入海口。转移的时候,因为需要记录子树中有多少是直接流向u的,所以开一个数组
    (g[u][j])表示以u为根的子树中有多少是直接流向u的。然而在转移的时候出现了问题。当从v转移到u时,我直接将流向v的货物又按照直接流向u进行计算的,这样显然是错误的。因为在v中最优的选择不一定是在u中也是最优的。我们还需要记录一个状态anc,表示所有的节点都流向anc,然后就可以大力转移了。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    
    using namespace std;
    
    const int N = 100 + 10;
    
    typedef long long LL;
    struct Edge {
    	int v, d, nxt;
    } e[N << 1];
    
    int head[N], cnt;
    int wgt[N], g[N][N], n, m, INF = 2e9 + 10;
    int stk[N], idx, dis[N];
    LL f[N][N][N][2], tmp[N][N];
    
    void AddEdge(int u, int v, int d) {
    	e[ ++ cnt].v = v;
    	e[cnt].d = d;
    	e[cnt].nxt = head[u];
    	head[u] = cnt;
    } 
    
    void dfs(int u) {
    	stk[++ idx] = u;
    	for(int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].v;
    		dis[v] = dis[u] + e[i].d;
    	//	printf("dep[%d] = %d
    ", v, dis[v]);
    		dfs(v);
    		for(int k = 1; k <= idx; k ++) {//都流向节点anc 
    	     	for(int j = m; j >= 0; -- j) {//j个伐木场 
    			    int anc = stk[k];
    			    f[u][j][anc][0] += f[v][0][anc][0];
    			    f[u][j][anc][1] += f[v][0][u][0];
    				for(int l = 0; l <= j; l ++) {
    					f[u][j][anc][0] = min(f[u][j][anc][0], f[u][j - l][anc][0] + f[v][l][anc][0]);
    					f[u][j][anc][1] = min(f[u][j][anc][1], f[u][j - l][anc][1] + f[v][l][u][0]);
    				}
    			}
    		}
    	}
    	for(int k = 1; k <= idx; k ++) {//都流向节点anc 
        	for(int j = 0; j <= m; ++ j) {//j个伐木场 
    			int anc = stk[k];
    			if( j >= 1)
    		    	f[u][j][anc][0] = min(f[u][j][anc][0] + wgt[u] * (dis[u] - dis[anc]), f[u][j - 1][anc][1]);   
    		    else f[u][j][anc][0] += wgt[u] * (dis[u] - dis[anc]);
    		}
    	}
    	idx --;
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for(int i = 1; i <= n; i ++) {
    		int fa, d;
    		scanf("%d%d%d", &wgt[i], &fa, &d);
    		AddEdge(fa, i, d);
    	}
    	dfs(0);
    	printf("%lld
    ", f[0][m][0][0]);
    }
    
  • 相关阅读:
    无名信号量在多线程间的同步
    ftok函数例子
    strerror和perror函数详解
    lockf函数的使用
    背包问题-2动态规划【正解】
    递归思想即背包问题
    生产者消费者问题(基于线程和无名信号量)
    eclipse 安装python后pydev不出现
    Eclipse+pydev解决中文显示和注释问题的方法大全
    MyEclipse10配置PyDev进行Python开发
  • 原文地址:https://www.cnblogs.com/wyy0804/p/13715180.html
Copyright © 2020-2023  润新知