Suzhou Adventure

11 篇文章 0 订阅
3 篇文章 0 订阅

描述

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 each village 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;
}



文字冒险是一种以文字为基础的游戏体验,玩家通过阅读描述和输入指令的方式进行游戏。这种游戏常常让玩家在一个虚拟世界中扮演主角,通过与游戏中的角色互动解决问题,达到完成故事情节的目标。 在一个文字冒险游戏中,玩家将通过阅读游戏中的文字描述了解游戏世界的背景、情节以及所处的环境。根据游戏情节的发展,玩家需要利用自己的想象力和逻辑推理能力来解决游戏中的谜题和困难。玩家通过输入指令来控制主角进行行动,例如“向前走”、“拿起钥匙”等等。游戏会根据玩家输入的指令进行相应的反馈,继续推动故事情节的发展。 文字冒险游戏依赖于玩家的想象力和阅读理解能力。玩家需要根据游戏中描述的场景和物品来确定下一步行动,同时还需要运用逻辑思维来解决谜题。由于文字冒险游戏没有图像或声音的辅助,玩家必须通过想象力来构建游戏世界,这种体验带来了无限的可能性和创造力。 文字冒险游戏曾经是游戏界的热门类型,尤其在早期个人电脑的时代。随着技术的进步,图形化和声音化的游戏体验逐渐成为主流,文字冒险游戏的人气有所下降。然而,一些游戏开发者仍然推出新的文字冒险游戏,以保留这种传统游戏形式的魅力。 总的来说,文字冒险游戏是一种让玩家通过阅读和输入指令的方式与虚拟世界进行互动的游戏。这种游戏体验依赖于玩家的想象力和阅读理解能力,带来了独特的创造力和挑战。即使在图形化游戏主导的时代,文字冒险游戏仍然保留着一定的市场和受众。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值