小胖守皇宫算法C++代码实现

  一、问题   

     huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。 可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。 帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

输入格式

输入文件中数据表示一棵树,描述如下:

第1行 

第2行至第

对于一个

输出格式

输出文件仅包含一个数,为所求的最少的经费。

由于宫殿节点图是树的形状,所以很明显这是树形DP。

首先二维状态,dp[i][j],j∈{1,2,3}

dp[i][1]表示这个点被自己守卫。

dp[i][2]表示这个点被父亲守卫。

dp[i][3]表示这个点被儿子守卫。

根据属性DP惯用套路,首先大法师(DFS)搜索到叶节点,然后向上更新。

如果这个点被自己守卫,那么他的儿子可能有三种状态,既可能是自己守卫,又可能被父亲守卫,还有可能被它的儿子守卫。

用s来代表x的儿子,所以:

dp[x][1] += min(dp[s][2],min(dp[s][3],dp[s][1]));

如果这个点被父亲守卫,那么他的儿子只可能被自己守卫,或者被它的儿子守卫。

dp[x][2] += min(dp[s][1],dp[s][3]);

那么最困难的是这个点被自己的儿子守卫,那么他的所有儿子同样是两种状态,被自己守卫或者被它的儿子守卫。且一定存在一个儿子被自己守卫。

如果更新了一圈后,发现所有的儿子自己守卫的代价都要大于它们的儿子守卫它们的价值(即x的儿子s守卫的价值大于s的儿子守卫的价值),我们需要加上一个s自己守卫和s的儿子守卫的差量,并且保证这个差量最小。

注意把所有点自己守卫自己的情况先赋上值。

二、代码实现

#include<cstdio>
#include<algorithm>
#define N 1555
using namespace std;
int money[N];
int son[N][N];
int dp[N][4];
void dfs(int x)
{
    if(!son[x][0])
    {
        dp[x][1] = money[x];
        dp[x][3] = money[x];
        dp[x][2] = 0;
        return ;
    }else
    {
        for(int i = 1;i<=son[x][0];i++)
        {
            dfs(son[x][i]);
        }
        for(int i = 1;i<=son[x][0];i++)
        {
            int s = son[x][i];
            dp[x][1] += min(dp[s][2],min(dp[s][3],dp[s][1]));//自己 
            dp[x][2] += min(dp[s][1],dp[s][3]);//父亲 
        }
 bool flag = 0;
        int bu = 2147438647;
        for(int i = 1;i<=son[x][0];i++)
        {
            int s = son[x][i];
            dp[x][3] += min(dp[s][1],dp[s][3]);
            if(dp[s][3]>=dp[s][1])
            {
                flag = 1;
            }
            bu = min(bu,dp[s][1]-dp[s][3]);
        }
        if(flag==0)
        {
            dp[x][3]+=bu;
        }
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    int root;
    for(int i = 1;i<=n;i++)
    {
        int num;
        scanf("%d",&num);
        if(i==1)
        {
            root = num;
        }
        scanf("%d",&money[num]);
        dp[num][1] = money[num];
        scanf("%d",&son[num][0]);
        for(int j = 1;j<=son[num][0];j++)
        {
            scanf("%d",&son[num][j]);
        }
    }
    dfs(root);
 printf("%d",min(dp[root][1],dp[root][3]));
}
 
 

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
抱歉,作为一个AI语言模型,我无法提供完整的代码实现一个复杂的系统。但我可以提供一些思路和关键点来帮助您开始编写这样一个系统。 1. 需求分析 首先,您需要确定系统的需求和功能。例如,您可能需要创建以下元素: - 用户账户:用户需先注册账户才能下单。 - 菜单:您需要维护食堂提供的所有菜品的列表,并可以更新和编辑菜单。 - 订单记录:系统需要记录每个用户的所有订单和订单详细信息。 - 支付:您可能需要整合一个在线支付平台(如支付宝)以方便用户支付订单。 2. 数据库设计 一旦您确定了系统的需求和功能,那么您需要为系统设计数据库结构。具体来说,您需要定义以下内容: - 用户表:包含用户的用户名、密码等个人信息。 - 菜单表:描述食堂供应的所有菜品及其价格。 - 订单表:记录每个用户的所有订单信息,包括所选菜品、数量、时间戳等。 - 支付记录表:用于记录用户的支付信息。 3. 用户界面 接下来您需要考虑设计用户界面以方便用户使用系统。您可以考虑创建以下页面: - 注册页面:用户可以在此页面上注册账户,提供其个人信息。 - 登录页面:用户需要在此页面上登录以使用系统。 - 菜单页面:显示所有可供订购的菜品和价格,用户可以通过此页面选择所需的菜品。 - 订单页面:显示用户的订单历史记录,包括每个订单的详细信息。 - 支付页面:当用户下单时,它会被导向到此页面以完成付款。 4. 开发 最后,您需要开始编写代码实现系统。您需要使用编程语言和框架来实现以下功能: - 用户管理:包括注册,登录和用户个人信息维护 - 菜单管理:及时更新食堂的供菜情况,保证菜单信息准确无误。 - 订单管理:处理用户对所选菜品进行下单并生成订单。 - 支付管理:整合与线上支付平台(如支付宝)的接口,以方便用户支付订单。 总的来说,一个食堂订餐系统需要花费很多时间和精力来设计和实现,但它将为您的用户提供很大的便利,并带来很多潜在的好处,如更好的餐厅管理和优化订单流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大王算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值