uva 12452 Plants vs. Zombies HD SP (树DP)
Problem I: Plants vs. Zombies HD Super Pro
Plants versus Zombies HD Super Pro is a game played not a grid, but on a connected graph G with no cycles (i.e., a tree). Zombies live on edges of the tree and chew through edges so that tree falls apart! Plants can be purchased and placed on vertices of the tree to protect the tree from falling apart. It is not possible to plant more than one plant on the same vertex. A plant protects one or more adjacent edges, depending on the strength and capabilities of the plant.
The Almanac offers you to buy any of three different types of plants:
- PEASHOOTERS: These are your first line of defense and can shoot peas along any one edge (of your choosing) adjacent to the vertex upon which it is placed. Cost: $100 per plant.
- SPLIT PEAS: These are hard working pea shooters and can shoot peas along any two edges (of your choosing) adjacent to the vertex upon which it is placed. Cost: $175 per plant.
- STARFRUIT: Having just visited the dentist, a STARFRUIT is very upset and shoots stars along all edges adjacent to the vertex upon which it is placed. Cost: $500 per plant.
Your goal is to protect the tree from the Zombies by having every edge covered by at least one plant, and doing so spending the least amount of money. You can buy more than one of each type of plant, but you can only plant at most one plant on each vertex.
Input Format
The input starts with an integer T - the number of test cases (T <= 100). T cases follow, each starting with the integer N on the first line, the number of vertices in G (2 <= N <= 10,000). N-1 line follows, each containing two space separated integers u and v (0 <= u,v <= N-1, u ≠ v) - describing an edge.
Output Format
For each test case, print on a separate line the minimum cost of protecting the tree, formatted like in the sample output.
Sample Input
2
2
0 1
3
0 1
1 2
Sample Output
$100
$175
In the second case we can put a Split Pea on the vertex 1.
题意: 给一颗n个点的树,每个点上只能放一种植物,共有三种植物,第一种可以覆盖与种植点相邻的一条边,费用是100,第二种是可以覆盖两条边,费用是175,第三种是可以覆盖所有边,费用500。求最小花费的金额,使得树上每一条边都能被覆盖。
思路:果断树DP。设dp[u][0]表示以u为根节点且u不覆盖u到他父亲节点的边的最小费用,dp[u][1]表示以u为根节点且u覆盖u到他父亲节点的边的最小费用。
然后分四种情况考虑状态转移。以下用v表示u的子节点
1.u不种植物:dp[u][0] = dp[v][1],而且不种植物是不可能连接父节点,即无dp[u][1]
2.u种第一种: dp[u][0] = dp[v][0] (选一个子节点) + dp[v][1] (剩余的所有子节点之和) + cost[1]
dp[u][1] = dp[v][1] (所有子节点之和) + cost[1]
3.u种第二种: dp[u][0] = dp[v][0](选两个子节点) + dp[v][1] (剩余所有子节点) + cost[2]
dp[u][1] = dp[v][0] (选一个子节点) + dp[v][1] (剩余所有子节点) + cost[2]
4.u种第三种: dp[u][0] 是不可能的
dp[u][1] = dp[v][0/1](所有子节点) + cost[3]
至于选择哪一个子节点,这里要用贪心,选一个差值最大的来搞,记录下sum1和sum0,以及最大差值dmx,次大差值dmx2
注意下使用第三种植物的时候不能简单用sum1和sum0,因为有dp[v][1] < dp[u][0]的情况存在,今天比赛就是坑这个位置了,遗憾啊。。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 1e9;
const int N = ; struct _edge{
int v,next;
};
_edge edge[N*];
int first[N],n,ecnt;
int dp[N][];
int cost[]; inline void add(int u,int v)
{
edge[ecnt].v = v;
edge[ecnt].next = first[u];
first[u] = ecnt++;
} void dfs(int u,int fa)
{
dp[u][] = dp[u][] = INF;
bool flag = ;
int sum1,sum0,dmx,dmx2;
sum1=sum0=;
int sum3=;
dmx=dmx2=;
for(int e=first[u];e!=-;e=edge[e].next)
{
int v = edge[e].v;
if(v==fa) continue;
flag = ;
// 1:
dfs(v,u);
sum1 += dp[v][];
sum0 += dp[v][];
sum3 += min(dp[v][],dp[v][]);
int d = dp[v][]-dp[v][];
if(d>dmx2)
{
dmx2 = d;
if(dmx2 > dmx)
{
swap(dmx,dmx2);
}
}
}
if(flag)
{
dp[u][]=;
dp[u][]=cost[];
return;
}
dp[u][] = min(sum1 - dmx + cost[],sum1 - dmx - dmx2 + cost[]);
dp[u][] = min(dp[u][],sum1);
dp[u][] = min(min(sum1 + cost[],sum1 - dmx + cost[]),sum3 + cost[]);
} void run()
{
memset(first,-,sizeof(first));
ecnt=;
scanf("%d",&n);
int u,v;
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(,-);
// for(int i=0;i<n;i++)
// {
//// printf("%d: %d %d\n",i,dp[i][0],dp[i][1]);
// }
printf("$%d\n",min(dp[][],dp[][]));
} int main()
{
//freopen("in","r",stdin);
cost[]=;cost[]=;cost[]=;
int _;
scanf("%d",&_);
while(_--)
run();
return ;
}
uva 12452 Plants vs. Zombies HD SP (树DP)的更多相关文章
- ZOJ 4062 Plants vs. Zombies(二分答案)
题目链接:Plants vs. Zombies 题意:从1到n每个位置一棵植物,植物每浇水一次,增加ai高度.人的初始位置为0,人每次能往左或往右走一步,走到哪个位置就浇水一次.求m步走完后最低高度的 ...
- Plants vs. Zombies(二分好题+思维)
Plants vs. Zombies http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5819 BaoBao and DreamG ...
- zoj4062 Plants vs. Zombies 二分+模拟(贪心的思维)
题目传送门 题目大意:有n个植物排成一排,标号为1-n,每株植物有自己的生长速度ai,每对植物浇一次水,该株植物就长高ai,现在机器人从第0个格子出发,每次走一步,不能停留,每一步浇一次水,总共可以走 ...
- bzoj 3572世界树 虚树+dp
题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...
- bzoj 2286 [Sdoi2011]消耗战 虚树+dp
题目大意:多次给出关键点,求切断边使所有关键点与1断开的最小费用 分析:每次造出虚树,dp[i]表示将i和i子树与父亲断开费用 对于父亲x,儿子y ①y为关键点:\(dp[x]\)+=\(dismn( ...
- 51nod1812树的双直径(换根树DP)
传送门:http://www.51nod.com/Challenge/Problem.html#!#problemId=1812 题解:头一次写换根树DP. 求两条不相交的直径乘积最大,所以可以这样考 ...
- bzoj1791[IOI2008]Island岛屿(基环树+DP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...
- [bzoj2878][Noi2012]迷失游乐园(基环树dp)
[bzoj2878][Noi2012]迷失游乐园(基环树dp) bzoj luogu 题意:一颗数或是基环树,随机从某个点开始一直走,不走已经到过的点,求无路可走时的路径长期望. 对于一棵树: 用两个 ...
- CF456D A Lot of Games (字典树+DP)
D - A Lot of Games CF#260 Div2 D题 CF#260 Div1 B题 Codeforces Round #260 CF455B D. A Lot of Games time ...
随机推荐
- Fragment 懒加载
我们在遇到Activity嵌套Fragment的时候经常会遇到多个Fragment页面同时加载数据,一开始的时候就初始化很多页面,有的甚至进入页面的时候,会造成缓慢的现象,下面我们就针对这个问题做一下 ...
- python 基础 1.5 python数据类型(二)--列表常用方法示例
#/usr/bin/python #coding=utf-8 #@Time :2017/10/12 23:30 #@Auther :liuzhenchuan #@File :列表.py lis ...
- TCP/IP状态详解
今天犯懒了,本来自己也做了一些相应的笔记,但是发现这篇写的更好一些,简单易懂,而且有图有真相,为了方便以后查看,在此转载了,在此基础上加了自己的笔记 TCP正常建立和关 ...
- 在java项目中使用protobuf
1 通用方式 第一步,定义数据结构 第二步,使用protoc.exe生成java代码 第三步,序列化 第四步,反序列化 2 grpc方式 grpc官方推荐的方式,通过maven插件来生成java代码. ...
- Java反射机制简单学习
java中除了基本数据类型,几乎都为对象.例如 Person p=new Person(); 这句语句表明了p是Person类的一个实例对象.但其实,Person也是一个实例对象,它是Class类的实 ...
- 谷歌postman插件的安装与使用
下载地址:http://pan.baidu.com/s/1kTh1g4B 安装方法: 1.下载并解压 2.解压后.打开谷歌浏览器.选择很多其它工具→扩展程序,如图 3.勾选开发人员模式 4.选择载入正 ...
- 怎样拆分View Controller进而实现轻量级的View Controller[UIKit]
參考文章来自objcio站点 为什么要编写轻量级的View Controller?? 1.作为iOS项目中最大的文件,ViewControllers中的代码复用率差点儿是最低的 2.重量级的V ...
- Golang JSON操作汇总
直接把结构体编码成json数据 package main import ( "encoding/json" "fmt" _ "os" ) t ...
- API的理解和使用——单线程架构
核心知识点: 1.单线程机制:所有命令放在一个队列中 2.为什么Redis单线程这么快?内存中执行.非IO阻塞.避免线程切换和竞态产生的消耗. 3.单线程的问题?一个命令不能执行太长时间,不然会阻塞其 ...
- CentOS下配置静态IP
第一.在VMware中进行配置使用桥接的方式.点击编辑选择虚拟网络编辑器 选择桥接模式,选择桥接到外部的网卡.选择我们主机下的网卡 第二步.配置虚拟机使用桥接模式 第三步:启动虚拟机进入到 /etc/ ...