警卫安排 题解

来源:互联网 发布:ubuntu zip压缩文件夹 编辑:程序博客网 时间:2024/04/30 02:55

警卫安排(security.pas/c/cpp

一个重要的基地被分为n个连通的区域。出于某种神秘的原因,这些区域以一个区域为核心,呈一颗树形分布。

在每个区域安排警卫所需要的费用是不同的,而每个区域的警卫都可以望见其相邻的区域,只要一个区域被一个警卫望见或者是安排有警卫,这个区域就是安全的。你的任务是:在确保所有区域都是安全的情况下,找到安排警卫的最小费用。

 

输入数据

    第一行n,表示树中结点的数目。

    接下来的n行描述了n个区域的信息,每一行包含的整数依次为:区域的标号i(0<i<=n),在区域i安排警卫的费用k,区域i的子结点数目m,接下来m个数为区域i的子结点编号。

 

输出数据

    一行一个整数,为最小的安排费用。

 

样例输入与输出

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

 

数据范围

    对于所有的数据,0<n<=720

 

 

 

这道题是明显的DP,他的分布是树型的。数据规模小,只要DFS+DP即可

每个安全结点i都有3个合法状态,分别为:

1.被父亲结点上安排的警卫看到,设为f[i][0]

2.在该结点安排警卫,设为f[i][1]

3.被子结点上安排的警卫看到,设为f[i][2]

现在只需针对三种状态,设计出状态转移方程。

对于f[i][0]i的每个子节点要么安排警卫,要么被其子结点安排的警卫看到,所以有:

f[i][0]=min(f[k][1],f[k][2]), ki的子结点

对于f[i][1]i的每个子结点可以任取一种状态,所以有:

f[i][1]= min(f[k][0],f[k][1],f[k][2])+w[i], ki的子结点

对于f[i][2],则需要枚举一个子结点安排警卫,其他子结点可任取状态2和状态3,所以有:

f[i][2]= min(f[k][1],f[k][2])+f[j][1]ki的子结点

j为枚举的点,kj

 

状态转移方程并不难想,关键是它的分类情况

pascal:

 

 

c:

 

原创粉丝点击