zoukankan      html  css  js  c++  java
  • icpc2020南京站 M.Monster Hunter (树形背包)

    题目链接:https://ac.nowcoder.com/acm/problem/216013

    (dp[i][j][0/1]) 表示杀到第 (i) 个节点,已经用魔法杀了 (j) 个怪物,当前节点使不使用魔法,所消耗的最小能量

    注意下树形背包的写法

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 2010; 
    const ll inf = 1ll << 60ll;
    
    int T, n, m;
    int a[maxn];
    ll tmp[maxn][2], dp[maxn][maxn][2];
    
    int h[maxn], cnt = 0;
    struct E{
    	int to, next;
    }e[maxn << 1];
    void add(int v, int u){
    	e[++cnt].next = h[u];
    	e[cnt].to = v;
    	h[u] = cnt;
    }
    
    int sz[maxn];
    
    void dfs(int u, int par){
    	sz[u] = 1;
    	dp[u][0][0] = a[u];
    	dp[u][1][1] = 0;
    	for(int i = h[u] ; i != -1 ; i = e[i].next){
    		int v = e[i].to;
    		if(v == par) continue;
    		
    		dfs(v, u);
    		
    		for(int j = 0 ; j <= sz[u] + sz[v] ; ++j) tmp[j][0] = tmp[j][1] = inf;
    		for(int j = 0 ; j <= sz[u] ; ++j){
    			for(int k = 0 ; k <= sz[v] ; ++k){
    				tmp[j + k][0] = min(tmp[j + k][0], dp[u][j][0] + dp[v][k][0] + a[v]);
                    tmp[j + k][0] = min(tmp[j + k][0], dp[u][j][0] + dp[v][k][1]);
                    tmp[j + k][1] = min(tmp[j + k][1], dp[u][j][1] + dp[v][k][0]);
                    tmp[j + k][1] = min(tmp[j + k][1], dp[u][j][1] + dp[v][k][1]);
    			}
    		}
    		
    		for(int j = 0 ; j <= sz[u] + sz[v] ; ++j){
    			dp[u][j][1] = tmp[j][1];
    			dp[u][j][0] = tmp[j][0];
    		}
    		
    		sz[u] += sz[v];
    	}
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	T = read();
    	
    	while(T--){
    		memset(h, -1, sizeof(h));
    		n = read();	
    		
    		for(int i = 0 ; i <= n ; ++i){
    			for(int j = 0 ; j <= n ; ++j){
    				dp[i][j][0] = dp[i][j][1] = inf;
    			} 
    		} 
    
    		cnt = 0;
    		
    		int x;
    		for(int i = 2 ; i <= n ; ++i){
    			x = read();
    			add(i, x), add(x, i);
    		}
    		for(int i = 1 ; i <= n ; ++i) a[i] = read();
    		
    		dfs(1, 0);
    		
    		for(int i = 0 ; i <= n ; ++i) printf("%lld ", min(dp[1][i][0], dp[1][i][1]));
    		printf("
    ");
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    Android 编程下 Eclipse 恢复被删除的文件
    Android 编程下背景图片适配工具类
    Android 编程下 Managing Your App's Memory
    Android 编程下代码之(QQ消息列表滑动删除)
    Android 编程下 Canvas and Drawables
    Android 编程下 AlarmManager
    Android 编程下去除 ListView 上下边界蓝色或黄色阴影
    Java 编程下字符串的 16 位、32位 MD5 加密
    C#枚举类型和int类型相互转换
    MVC和普通三层架构的区别
  • 原文地址:https://www.cnblogs.com/tuchen/p/14194799.html
Copyright © 2011-2022 走看看