hihoCoder #1104 Suzhou Adventure

传送门:http://hihocoder.com/problemset/problem/1104

解题思路:

  这是一道树上的动态规划问题 首先将多叉树转化为二叉树存储,再根据题中推荐访问的村庄地点预先处理得到必须访问的村庄集合,以便在动态规划时使用辅助决策,根据状态转移方程求解。

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstring>
 4 #include <set>
 5
 6 int score[101];
 7 int N, K, M;
 8 int dp[101][101];
 9 std::vector<int> edges[101];
10 int b[101] = {0};
11 int c[101] = {0};
12 std::set<int> must;
13
14 void makeTree()
15 {
16     int a,b;
17     for (int i = 0; i < N-1; ++i) {
18         std::cin >> a >> b;
19         edges[a].push_back(b);
20         edges[b].push_back(a);
21     }
22 }
23
24 void convertToBT(int node, int par)
25 {
26     for (int i = 0; i < edges[node].size(); ++i) {
27         if (edges[node][i] != par) {
28             b[edges[node][i]] = c[node];
29             c[node] = edges[node][i];
30             convertToBT(edges[node][i], node);
31         }
32     }
33 }
34
35 void preProcess(int node, int par)
36 {
37     if (edges[node].size() == 1 && edges[node][0] == par) return;
38
39     for (int i = 0; i < edges[node].size(); ++i) {
40         if (edges[node][i] != par) {
41             preProcess(edges[node][i], node);
42             if (must.count(edges[node][i])) {
43                 must.insert(node);
44             }
45         }
46     }
47 }
48
49 int dfs(int n, int m)
50 {
51     if (dp[n][m] != -1) return dp[n][m];
52     if (m == 0 ) {
53         if (n == 0 || ( must.count(n) == 0 && dfs(c[n],0)==0 && dfs(b[n], 0) == 0)) return dp[n][m] = 0;
54         else return dp[n][m] = -2;
55     }
56     if (n == 0 && m != 0) {return dp[n][m] = -2;}
57
58
59     int maxm = -2;
60     if (must.count(n) == 0) {
61         maxm = dfs(b[n], m);
62     }
63
64     for (int i = 0; i < m; ++i) {
65         if (dfs(c[n], i) == -2 || dfs(b[n], m-1-i) == -2) continue;
66         else {
67             maxm = std::max(maxm, dp[c[n]][i] + dp[b[n]][m-1-i] + score[n]);
68         }
69     }
70
71     return dp[n][m] = maxm;
72
73 }
74
75 int main()
76 {
77     std::cin >> N >> K >> M;
78     for (int i = 1; i <= N; ++i) {
79         std::cin >> score[i];
80     }
81     int v;
82     for (int i = 0; i < K; ++i) {
83         std::cin >> v;
84         must.insert(v);
85     }
86     if (K > M) {std::cout << -1 << std::endl; return 0;}
87     memset(dp, -1, sizeof dp);
88     makeTree();
89     convertToBT(1,-1);
90     preProcess(1, -1);
91     int maxm = dfs(1, M);
92     if (maxm < 0) std::cout << -1 << std::endl;
93     else std::cout << maxm << std::endl;
94 }
时间: 2024-10-19 07:45:52

hihoCoder #1104 Suzhou Adventure的相关文章

HihoCoder 1104 : Suzhou Adventure(树形DP)

Suzhou Adventure 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi is taking an adventure in Suzhou now. There are N beautiful villages in Suzhou which are numbered from 1 to N. They connected by N-1 roads in such a way that there is excactly one way

Suzhou Adventure,hihocoder 1104

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi is taking an adventure in Suzhou now. There are N beautiful villages in Suzhou which are numbered from 1 to N. They connected by N-1 roads in such a way that there is excactly one way to travel from on

hiho一下第76周《Suzhou Adventure》

我是菜鸡,我是菜鸡,我是菜鸡....重要的事说三遍 算是第一次做树形dp的题吧,不太难.. 园林构成一棵树,root为1,Hi从root出发,有k个园林必须玩,每个园林游玩后会得到权值w[i],最多玩M个园林. 经过的园林必须玩,问可得到的最大权值和. 题目链接:http://hihocoder.com/problemset/problem/1104 经典的树形dp,dp[i][j],表示以i为根的子树选j个结点可得的最大权值和. 这样dp[root][num] = g[son_num][num

[hihoCoder#1381]Little Y&#39;s Tree

[hihoCoder#1381]Little Y's Tree 试题描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每次小J会删掉这个树中的k条边,这棵树被分成k+1个连通块.小J想知道每个连通块中最远点对距离的和. 这里的询问是互相独立的,即每次都是在小Y的原树上进行操作. 输入 第一行一个整数n,接下来n-1行每行三个整数u,v,w,其中第i行表示第i条边边权为wi,连接了ui,vi两点. 接下来一行一个整数q,表示有q组询问. 对于每组询问,第一行一个正整数k,接下来一

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

hihocoder [Offer收割]编程练习赛18 C 最美和弦(dp)

题目链接:http://hihocoder.com/problemset/problem/1532 题解:一道基础的dp,设dp[i][j][k][l]表示处理到第几个数,当前是哪个和弦错了几次初始x值是多少.这里还要再辅助一个val[k]表示处理到当前情况只错了k次的最小值是多少因为改变的不止是和弦还有初始值,可以看一下代码理解一下. #include <iostream> #include <cstring> #include <cstdio> #include &

1104: 零起点学算法11——求梯形面积

1104: 零起点学算法11--求梯形面积 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 6473  Accepted: 1875[Submit][Status][Web Board] Description 水题 Input 输入3个浮点数,分别表示上底.下底和高,中间用逗号隔开(题目包含多组数据) Output 输出梯形的面积,保留2位小数 Sample Input 2,4,5 Sample

hihocoder #1190 : 连通性&#183;四 点双联通分量

http://hihocoder.com/problemset/problem/1190?sid=1051696 先抄袭一下 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho. 老师告诉小Hi和小Ho:之前的分组出了点问题,当服务器(上次是连接)发生宕机的时候,在同一组的服务器有可能连接不上,所以他们希望重新进行一次分组.这一次老师希望对连接进行分组,并把一个组内的所有连接关联的服务器也视为这个组内

Hihocoder 太阁最新面经算法竞赛18

Hihocoder 太阁最新面经算法竞赛18 source: https://hihocoder.com/contest/hihointerview27/problems 题目1 : Big Plus 描述 Given an NxN 01 matrix, find the biggest plus (+) consisting of 1s in the matrix. size 1 plus size 2 plus size 3 plus size 4 plus 1 1 1 1 111 1 1