动态规划-树上dp-1757. 搜集钻石

2020-04-08 08:05:15

问题描述:

蒜国有 n 座城市,编号从 1 到 n,城市间有 n−1 条道路,且保证任意两座城市之间是连通的。每一座城市有一定数量的钻石。

蒜头君想在蒜国搜集钻石。他从城市 1 出发,每天他可以通过城市之间道路开车到另外的城市。当蒜头第一次到一个城市的时候,他可以搜集完这个城市的所有钻石,如果他后面再来到这个城市,就没有砖石可以收集了。

蒜头君只有 k 天时间,请你帮算蒜头君计算他最多可以搜集多少钻石。

num表示每个城市的钻石数量,mp表示城市所有的道路。

样例

样例 1:

输入: n=3,k=2,num=[3,8,3],mp=[[1,3],[3,2]]
输出: 14
解释:
他能得到所有的钻石

样例 2:

输入: n=6,k=2,num=[5,9,8,4,9,2],mp=[[1,6],[6,2],[2,5],[5,3],[5,4]]
输出: 16
解释:
他可以得到第1、2、6个城市中的钻石

注意事项

  • 1 <= n <= 100
  • 0 <= k <= 200
  • nums[i] <= 1000
  • 保证任意两座城市可以直接或间接到达

问题求解:

    int m;
    int[] nums;
    int[][][] dp = new int[210][210][2];
    List<Integer>[] graph;
    
    void dfs(int fa,int u)
    {
    	int l=graph[u].size();
    	for(int i=0;i<=m;i++)
    	{
    		dp[u][i][1]=dp[u][i][0]=nums[u - 1];
    	}
    	for(int i=0;i<l;i++)
    	{
    		int v=graph[u].get(i);
    		if(v==fa) continue;
    		dfs(u,v);
    		for(int j=m;j>=1;j--)
    		{
    			for(int e=0;e<=j-1;e++)
    			{
    				if(j-e>=2)
    				{
    					dp[u][j][1]=Math.max(dp[u][j][1],dp[u][e][1]+dp[v][j-e-2][1]);
    					dp[u][j][0]=Math.max(dp[u][j][0],dp[u][e][0]+dp[v][j-e-2][1]);//前面的不回来
    				}
    				dp[u][j][0]=Math.max(dp[u][j][0],dp[u][e][1]+dp[v][j-e-1][0]);//后面的不回来
    			}
    		}
    	}
    }
    
    public int getCount(int n, int k, int[] num, int[][] mp) {
        m = k;
        nums = num;
        graph = new List[n + 1];
        for (int i = 1; i <= n; i++) graph[i] = new ArrayList<>();
        for (int[] e : mp) {
            graph[e[0]].add(e[1]);
            graph[e[1]].add(e[0]);
        }
        dfs(-1, 1);
        return dp[1][m][0];
    }

  

 

 

 

 

posted @ 2020-04-08 08:06  hyserendipity  阅读(196)  评论(0编辑  收藏  举报