zoukankan      html  css  js  c++  java
  • [JZOJ 5788] 餐馆

    思路:
    考虑树形dp。
    我们设\(dp[i][j][0/1]\)表示在\(i\)为根的子树中花费\(j\)单位时间,最终回到/不必回到\(i\)的最大收益。
    转移三种:
    \(dp[x][j][0] = max(dp[x][j][0],dp[x][j - k - 2][0] + dp[y][k][1]);\)
    \(dp[x][j][0] = max(dp[x][j][0],dp[x][j - k - 1][1] + dp[y][k][0]);\)
    \(dp[x][j][1] = max(dp[x][j][1],dp[x][j - k - 2][1] + dp[y][k][1]);\)
    搞定.

    #include <bits/stdc++.h>
    using namespace std;
    inline int read() {
    	int q=0,f=1;char ch = getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')f = -1;ch=getchar();
    	}
    	while(isdigit(ch)){
    		q=q*10+ch-'0';ch=getchar();
    	}
    	return q*f;
    }
    const int maxn = 600;
    struct edge {
    	int to;
    	int nxt;
    }e[maxn << 1];
    int cnt;
    int head[maxn<<1];
    inline void add_edge(int u,int v) {
    	e[++cnt].to = v;
    	e[cnt].nxt = head[u];
    	head[u] = cnt;
    }
    inline void Add_edge(int u,int v) {
    	add_edge(u,v);
    	add_edge(v,u);
    	return;
    }
    int dp[maxn][maxn][2];
    int m;int n;
    int a[maxn];
    inline void dfs(int x,int fa) {
    	for(int i = head[x];i;i=e[i].nxt) {
    		int y = e[i].to;
    		if(y == fa) continue;
    		dfs(y,x);
    		for(int j = m;j >= 2; --j) {
    			for(int k = 0;k <= m; ++k) {
    				if(j - k - 2 < 0) break;
    				dp[x][j][0] = max(dp[x][j][0],dp[x][j - k - 2][0] + dp[y][k][1]);
    			}
    		}
    		for(int j = m;j >= 1; --j) {
    			for(int k = 0;k <= m; ++k) {
    				if(j - k - 1 < 0) break;
    				dp[x][j][0] = max(dp[x][j][0],dp[x][j - k - 1][1] + dp[y][k][0]);
    			}
    		}
    		for(int j = m;j >= 2; --j) {
    			for(int k = 0;k <= m; ++k) {
    				if(j - k - 2 < 0) break;
    				dp[x][j][1] = max(dp[x][j][1],dp[x][j - k - 2][1] + dp[y][k][1]);
    			}
    		}
    	}
    	for(int i = m;i >= 1; --i) {
    		dp[x][i][0] = max(dp[x][i][0],dp[x][i - 1][0] + a[x]);
    		dp[x][i][1] = max(dp[x][i][1],dp[x][i - 1][1] + a[x]);
    	}
    }
    int main () {
    	#ifdef ONLINE_JUDGE
    		freopen("dostavljac.in","r",stdin);
    		freopen("dostavljac.out","w",stdout);
    	#endif
    	n = read(),m = read();
    	for(int i = 1;i <= n; ++i) {
    		a[i] = read();
    	}
    	for(int i = 1;i < n; ++i) {
    		int x = read(),y = read();
    		Add_edge(x,y);
    	}
    	dfs(1,0);
    	printf("%d\n",dp[1][m][0]);
    	return 0;
    }
    
  • 相关阅读:
    整数反转
    两数之和
    设计模式-备忘录模式
    设计模式-迭代器模式
    设计模式-中介者模式
    设计模式-观察者模式
    C# OpenFileDialog和SaveFileDialog的常见用法
    SQL数据库表结构的修改(sql2005)
    C# 时间格式处理
    C# 集合类(四)
  • 原文地址:https://www.cnblogs.com/akoasm/p/9563839.html
Copyright © 2011-2022 走看看