Suzhou Adventure
2015-12-13 20:51
274 查看
描述
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 one village to another. Little Hi gives eachvillage a score according to its attractiveness. He is visiting village 1 now and plans to visit excatly M villages (including village 1) and maxize the total score of visited villages. Further more, K villages are recommended by Little Ho. He does not want
to miss these recommended villages no matter what their attractiveness scores are.
Note that Little Hi visits every village on his travel route. Passing a village without visiting it is not allowed. Please find the maximum total score Little Hi can get.
输入
The first line contains 3 integers N(1 <= N <= 100), K(1 <= K <= 5) and M(1 <= M <= N), representing the number of villages, the number of recommended villages and the number of villages Little Hi plans to visit.The second line contains N integers, the attractiveness scores of villages. The scores are between 1 to 100.
The third line contains K integers, the list of recommended villages.
The following N-1 lines each contain two integers a and b, indicating that village a and village b are connected by a road.
输出
The maximum scores Little Hi can get. If there is no solution output -1.样例输入
5 2 4 1 2 3 4 5 3 4 1 2 1 3 1 4 2 5
样例输出
10
这道题有两个条件:
1.所走的点的个数不能超过m个;
2.必须走那些推荐的点。
不能超过m个点就直接树形dp就好了,
可是需要走那些推荐的点,
做法:
将这些要走的推荐点直接走掉,并
将其所以祖父节点的值全部累加,统计个数并
标记,看其个数是否超过m了,不过在操作时需要
将多叉树转换成二叉树,记住一点建立二叉树后的
右子树实际上是左子树的兄弟。
调试了几个小时,真累。
#include <stdio.h> #include <vector> #include <string.h> #define DBUG printf ( "Here!\n" ) using namespace std; const int maxn = 205; struct node { int l, r, socre; } a[maxn]; int son[maxn], vis[maxn], use[maxn]; int dp[maxn][maxn], ans, to[maxn], m, fa[maxn]; vector < int > mp[maxn]; inline int Max ( int a, int b ) { return a > b ? a : b; } void create_tree ( int u ) //转换成二叉树 { int size = mp[u].size ( ); vis[u] = 1; for ( int i = 0; i < size; i ++ ) { int v = mp[u][i]; if ( vis[v] ) continue ; if ( fa[v] == -1 ) fa[v] = u; if ( a[u].l == -1 ) a[u].l = v; else a[ son[u] ].r = v; son[u] = v; create_tree ( v ); } } void front_print ( int u ) { printf ( "%d ", u ); if ( a[u].l != -1 ) front_print ( a[u].l ); if ( a[u].r != -1 ) front_print ( a[u].r ); } int dfs ( int i, int j ) { if ( dp[i][j] != -1 ) return dp[i][j]; if ( j == 0 ) return 0; int val = 0, add = 0; if ( use[i] == 0 ) { val = a[i].socre; add = -1; } if ( a[i].l == -1 && a[i].r == -1 ) return dp[i][j] = val; if ( a[i].l > 0 && a[i].r == -1 ) dp[i][j] = val+dfs ( a[i].l, j+add ); else if ( a[i].l == -1 && a[i].r > 0 ) dp[i][j] = Max ( val+dfs ( a[i].r, j+add ), dfs ( a[i].r, j ) ); else { dp[i][j] = Max ( dfs ( a[i].r, j ), val+dfs ( a[i].l, j+add ) ); //add可能为0,那么左子树就需要走a[i].l,j(一直错在这里) for ( int k = 0; k < j; k ++ ) //**而且不能加<=j,因为add为-1的情况也需要考虑,所以放上面做一次 { //printf ( "%d\n", k ); dp[i][j] = Max ( dp[i][j], val+dfs ( a[i].l, k )+dfs ( a[i].r, j-k+add ) ); } } //printf ( "%d %d %d %d %d %d\n", i, j, a[i].l, a[i].r, add, dp[i][j] ); return dp[i][j]; } void get_tag ( int u ) { while ( ~ u ) { //printf ( "%d\n", v ); if ( use[u] == 0 ) { ans = ans+a[u].socre; //加值 并个数减1 m --; use[u] = 1; //标记节点,证明已用 } u = fa[u]; } } int main ( ) { int n, k, u, v; memset ( son, -1, sizeof ( son ) ); memset ( fa, -1, sizeof ( fa ) ); memset ( dp, -1, sizeof ( dp ) ); memset ( use, 0, sizeof ( use ) ); scanf ( "%d%d%d", &n, &k, &m ); for ( int i = 1; i <= n; i ++ ) { scanf ( "%d", &a[i].socre ); a[i].l = a[i].r = -1; } for ( int i = 1; i <= k; i ++ ) scanf ( "%d", &to[i] ); for ( int i = 1; i < n; i ++ ) { scanf ( "%d%d", &u, &v ); mp[u].push_back ( v ); mp[v].push_back ( u ); } create_tree ( 1 ); for ( int i = 1; i <= k; i ++ ) get_tag ( to[i] ); //将to[i]的父节点全部加起来并标记 //printf ( "%d %d\n", ans, m ); //front_print ( 1 ); if ( m < 0 ) //这些必须走的点需要走的次数超过m printf ( "-1" ); else { ans = ans+dfs ( 1, m ); printf ( "%d", ans ); } return 0; }
相关文章推荐
- 嵌入式学习路线与方法的一个不错的讲座
- C语言中指针
- oracle database 11g 闪回技术
- AOJ 0121 Seven Puzzle {广度优先搜索}(*)
- 生成随机密码
- io流操作之文本读写代码
- Linux_SquidProxyServer代理服务器
- Q:无法打开源文件****.h?
- LeetCode--ADD Digits
- i5 6300HQ 和 i7 6700HQ
- 编写高质量iOS与OS X代码的52个有效的方法 之协议与分类
- Mysql数据库默认编码修改。
- 数组除去重复
- Javascript的变量和作用域问题(二)之作用域
- SGU 149. Computer Network( 树形dp )
- 《世界是数字的》读后感(3)
- Spring PropertyPlaceholderConfigurer
- io流操作之文件重命名代码
- 总结让图片在div中居中的方式
- 深拷贝和浅拷贝