【题解】警位安排( 树形 DP)
【题目描述】
一个重要的基地被分成了 n 个连通的区域 , 出于某种原因 , 这个基地以某一个区域为核
心,呈一树形分布。
在每个区域里安排警卫的费用是不同的,而每个区域的警卫都可以望见其相邻的区域 。
如果一个区域有警卫或是被相邻区域的警卫望见 , 那它就是安全的 , 你的任务是 : 在确保所
有的区域安全的状态下,使总费用最小。
【输入格式】
第一行 n ,表示树中结点的数目。
接下来 n 行,每行依次是:区域的编号;在此安排警卫的费用;它的子结点的个数 m ,
然后往后 m 个数,为它的子结点编号。
【输出格式】
一行一个数,为最小费用。
【输入样例】
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
【输出样例】
25
#include <cstdlib>
#include <fstream>
#include <cstring>
#include <iostream> using namespace std; ifstream fin("security.in");
ofstream fout("security.out"); int cnt_node=;//点的个数
bool fuqin[]={false};//判断是否有父节点 int head[]={},cnt=;
struct liansi{
int to;
int nxt;
};
liansi lian_son[]={};//链式前向星 int paying[]={};//每个警卫处要安排警察的费用
int p_state[][]={}; //状态 void add(int a,int b);//链式前向星
void plan(int size,int state); void add(int a,int b){
lian_son[++cnt].to=b;
lian_son[cnt].nxt=head[a];
head[a]=cnt;
return;
} void plan(int size,int state){
if(head[size]==-){//当前节点为数最底部
p_state[size][state]=;//如果状态为父亲看守 花费为0
if(state==){
p_state[size][]=paying[size]; //状态为自己看守 ,花费为自己安排警卫所付的钱
}
return;
} if(state==){//当前节点自己安排警卫
int sum=;
for(int hao=head[size];hao!=-;hao=lian_son[hao].nxt){
int minn=0x7fffff;
int son=lian_son[hao].to; if(p_state[son][]<)plan(son,);//它的儿子可以让父亲看守
minn=min(minn,p_state[son][]);//打擂 求最小 if(p_state[son][]<)plan(son,); //可以自己看守(为便利子孙)
minn=min(minn,p_state[son][]);//打擂 求最小 if(head[son]!=-){//它的儿子也可以让自己儿子看守 这里是说它的儿子有儿子
if(p_state[son][]<)plan(son,);
minn=min(minn,p_state[son][]); //打擂 求最小
}
sum+=minn;//加上所以儿子所用最小值
}
p_state[size][]=sum+paying[size];//再加上自己的安排警卫的钱,为当前节点安排警卫所花费最小金额
} if(state==){//如果让父亲看守
int sum=;
for(int hao=head[size];hao!=-;hao=lian_son[hao].nxt){
int minn=0x7fffff;
int son=lian_son[hao].to; if(p_state[son][]<)plan(son,);//当前节点的儿子要么自己看守
minn=min(minn,p_state[son][]); if(head[son]!=-){
if(p_state[son][]<)plan(son,);//要么有儿子就让儿子看守
minn=min(minn,p_state[son][]);
}
sum+=minn;
}
p_state[size][]=sum;
} if(state==){//表示当前节点由某一儿子看守
int Min=0x7fffff;
for(int hao=head[size];hao!=-;hao=lian_son[hao].nxt){
int sum=, meijv=lian_son[hao].to; //枚举看守儿子节点 for(int hao2=head[size];hao2!=-;hao2=lian_son[hao2].nxt){
int minn=0x7fffff, son=lian_son[hao2].to; if(son!=meijv){//计算非枚举子节点所要花费最小值 if(p_state[son][]<)plan(son,);
minn=min(minn,p_state[son][]);
if(head[son]!=-){
if(p_state[son][]<)plan(son,);
minn=min(minn,p_state[son][]);
}
sum+=minn;
}
}
if(p_state[meijv][]<)plan(meijv,);//计算枚举看守儿子看守的最小值
Min=min(Min,sum+p_state[meijv][]);
}
p_state[size][]=Min;
} return;
} int main(){
fin>>cnt_node; memset(head,-,sizeof(head)); for(int x=;x<=cnt_node;x++){
int s1ze=,paid=,cnt_son=;
fin>>s1ze>>paid>>cnt_son;//输入编号花费与子节点个数
paying[s1ze]=paid;
for(int y=;y<=cnt_son;y++){
int son=;
fin>>son;
fuqin[son]=true;//表示此编号有父节点
add(s1ze,son); //用链式前向星将父节点与子节点连接起来
}
} int gen=;//根
for(int i=;i<=cnt_node;i++){
if(fuqin[i]==false){//如果一个点没有父节点
gen=i;//那么它就是根
break;
}
} memset(p_state,-,sizeof(p_state));//将所有状态默认为-1 plan(gen,); //表示它自己放警卫 自己看守
plan(gen,);//表示让它儿子放警卫 让儿子看守
int ans=min(p_state[gen][],p_state[gen][]);//比较哪种费用最低
cout<<ans;
fout<<ans;
return ;
} /*
核心思路:
划分阶段:
0.由父亲看守,那么它的儿子要么自己看守,要么让它儿子看守
1.有由自己看守,那么自己的儿子可以不看守,也可以看守便利子孙
2.由某一个儿子看守,其它儿子照样可以选择自己看守,还是由自己的儿子看守
*/
【题解】警位安排( 树形 DP)的更多相关文章
- codeforces766E Mahmoud and a xor trip(按位统计+树形DP)
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 3月28日考试 题解(二分答案+树形DP+数学(高精))
前言:考试挂了很多分,难受…… --------------------- T1:防御 题意简述:给一条长度为$n$的序列,第$i$个数的值为$a[i]$.现让你将序列分成$m$段,且让和最小的一段尽 ...
- 【BZOJ1864】[Zjoi2006]三色二叉树 树形DP
1864: [Zjoi2006]三色二叉树 Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最 ...
- POJ1947 - Rebuilding Roads(树形DP)
题目大意 给定一棵n个结点的树,问最少需要删除多少条边使得某棵子树的结点个数为p 题解 很经典的树形DP~~~直接上方程吧 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v] ...
- hdu_Anniversary party_(树形DP入门题)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意:有N个人,N-1个人有自己的上司,每个人有一个快乐值,如果这个人参加了聚会,那么这个人的直 ...
- bzoj 4871: [Shoi2017]摧毁“树状图” [树形DP]
4871: [Shoi2017]摧毁"树状图" 题意:一颗无向树,选两条边不重复的路径,删去选择的点和路径剩下一些cc,求最多cc数. update 5.1 : 刚刚发现bzoj上 ...
- hdu5293 Tree chain problem 树形dp+线段树
题目:pid=5293">http://acm.hdu.edu.cn/showproblem.php?pid=5293 在一棵树中,给出若干条链和链的权值.求选取不相交的链使得权值和最 ...
- hdu3586 Information Disturbing 【树形dp】
题目链接 hdu3586 题解 二分 + 简单的树形dp 我正有练一下dp的必要了 #include<iostream> #include<cstdio> #include&l ...
- Hackrank Kingdom Division 树形DP
题目链接:传送门 题意: 给你一棵树,n个点 每个点可以染成红色和蓝色 但是红色的点与其相邻的点中必须有红色节点,蓝色也是 问你有多少种染色的方案 题解: 树形dp 先转化为有根树,取1为根 设定dp ...
随机推荐
- Codevs 1082 线段树练习 3
1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Maste 传送门 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的 ...
- 『重构--改善既有代码的设计』读书笔记----Replace Array with Object
如果你有一个数组,其中的元素各自代表不同东西,比如你有一个 QList<QString> strList; 其中strList[0]代表选手姓名,strList[1]代表选手家庭住址,很显 ...
- WF学习笔记(四)
1.使用WorkflowApplication.OnUnhandledException 处理Code异常 ,用于产生异常的Activity: public class ExceptionActivi ...
- javascript ajax请求
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- Discuz论坛下载与安装
Part1 Discuz下载 百度“discuz下载” 2. 找到下图这里 3. 选择你需要的版本,这里我选了X3.1版 4. 选择UTF-8简体下载 这是我下载好的文件 Part2 Discuz安装 ...
- JS类型、值和变量 笔记
非数字 JavaScript中的非数字值有一点特殊.他们和任何值都不相等,包括和本身也不相等. NaN == NaN => false NaN != NaN => true isNaN(N ...
- PHP实战开发教程
对于PHP初学者来说,一上手就学习庞大的PHP语法无疑很打击自信心.其实即便是很熟练的程序员,也未必对所有的语法非常熟悉.通常熟练的程序员比普通的程序员的优势在于对基本语法的理解非常透彻,而且常用的一 ...
- 通过try、except和else的使用来使Python程序更加“强壮”
在执行的程序中,难免会碰到因为一些原因如输入输出导致致命性错误产生的情况(如因为输入的文件名错误而导致无法运行相关的代码.).此时你不希望程序直接挂掉,而是通过显示一些信息,使其平稳的结束.此时,就可 ...
- GCC编译器的安装
1.GCC简介 GCC(GNU Compiler Collection)是一套功能强大.性能优越的编程语言编译器,它是GNU计划的代表作品之一.GCC是Linux平台下最常用的编译器,GCC原名为GN ...
- KVC 与 KVO 理解-b
KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一 ...