HDU 4044 GeoDefense (树形DP,混合经典)
题意:
给一棵n个节点的树,点1为敌方基地,叶子结点都为我方阵地。我们可以在每个结点安放炸弹,每点至多放一个,每个结点有ki种炸弹可选,且每种炸弹有一个花费和一个攻击力(1点攻击力使敌人掉1点hp)。敌人的目的是我方阵地,任意路线都有可能,但规定只能往下跑。问当有m钱时,最坏情况下最多能打掉敌人多少hp?(n<1001, m<201, ki>=0)
思路:
我竟然自己写出来了,咔咔~证明此题不难!
注意:某些点可能没有炸弹可选(即不能放炸弹);有0花费的炸弹;最坏情况下指的是敌人总是跑攻击力最小的那条路径。
本题说不出具体什么模型,混着来的。观察一下知道,如果本节点不放炸弹,那么所有子树就都得放炸弹,否则本节点往下走的攻击力必定为0。那么尽量炸弹放在更靠近根的地方应该是比较划算的(按常理)。
同样,分析一个节点。本节点为根的子树的攻击力=min(每个子树的攻击力)+(本节点的攻击力),这是短板原理。然后再考虑本节点,如果买了,直接在短板上加攻击力,前提是本节点只允许放1炸弹。
如何转移?先从将这子树花费为0的装进背包,如果有更好的再代替掉他。这一步暂时将dp[t][j]表示为以t为根的子树如果得到j元,至少能攻击敌人的hp。状态方程:dp[t][j]=max(dp[t][j], min(dp[t][j-k], dp[e.to][k]));。为什么有个min?因为要取短板。注意初始化问题。
由于可能会有免费炸弹,而每个点只需要考虑1个免费炸弹(只能放1个),其他免费炸弹删除掉(因为不划算啊),而且免费炸弹总是要先被考虑,否则的话就会重复。
#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=;
struct tower
{
int pri,pow;
}tow[N][]; struct node
{
int from,to,next;
node(){};
node(int from,int to,int next):from(from),to(to),next(next){};
}edge[N*]; int edge_cnt, head[N], cnt[N], dp[N][], n, m ;
void add_node(int from,int to)
{
edge[edge_cnt]=node(from, to, head[from]);
head[from]=edge_cnt++;
}
inline int cmp(tower a,tower b){return a.pri<b.pri;} void DFS(int t,int far)
{
node e;
int flag=;
for(int i=head[t]; i!=-; i=e.next)
{
e=edge[i];
if(e.to==far) continue;
DFS(e.to, t); for(int j=m; j>=; j-- ) //容量
{
dp[t][j]=min(dp[t][j], dp[e.to][]); //先装代价为0的,如果有更好的再代替掉。
for(int k=; k<=j; k++ ) //给此孩子k元,得到的最大攻击力。
dp[t][j]=max(dp[t][j], min(dp[t][j-k], dp[e.to][k]));
}
flag=; //标记是否叶子。
}
if(flag==) memset(dp[t], , sizeof(dp[t])); //叶子节点 //本节点的决策是01背包模型: 买 or 不买。(不买就只能靠孩子来防御)
for(int j=m; j>=; j-- ) //容量
{
int k=;
for( ; k<cnt[t] && !tow[t][k].pri; k++ ) //不用钱的,只留1个power最大的.
if(tow[t][k-].pow > tow[t][k].pow)
swap(tow[t][k],tow[t][k-]); for( k-- ; k<cnt[t]; k++) //物品
{
if(j-tow[t][k].pri>=)
dp[t][j]=max(dp[t][j], dp[t][j-tow[t][k].pri] + tow[t][k].pow ); //可以直接挡
}
}
} int main()
{
freopen("input.txt", "r", stdin);
int t, a, b; cin>>t;
while(t--)
{
edge_cnt=;
memset(head, -, sizeof(head));
memset(dp, 0x3f, sizeof(dp)); //注意初始化 scanf("%d",&n);
for(int i=; i<n; i++) //无向图
{
scanf("%d%d",&a,&b);
add_node(a,b);
add_node(b,a);
} scanf("%d",&m); //钱。
for(int i=; i<=n; i++)
{
scanf("%d",&cnt[i]);
for(int j=; j<cnt[i]; j++)
scanf("%d%d", &tow[i][j].pri, &tow[i][j].pow);
sort(tow[i], tow[i]+cnt[i], cmp); //免费的排前面
}
DFS(, -);
printf("%d\n",dp[][m]);
}
return ;
}
AC代码
HDU 4044 GeoDefense (树形DP,混合经典)的更多相关文章
- HDU 2196 Computer 树形DP经典题
链接:http://acm.hdu.edu.cn/showproblem.php? pid=2196 题意:每一个电脑都用线连接到了还有一台电脑,连接用的线有一定的长度,最后把全部电脑连成了一棵树,问 ...
- HDU 2196 Computer 树形DP 经典题
给出一棵树,边有权值,求出离每一个节点最远的点的距离 树形DP,经典题 本来这道题是无根树,可以随意选择root, 但是根据输入数据的方式,选择root=1明显可以方便很多. 我们先把边权转化为点权, ...
- HDU 4044 GeoDefense(动态规划)
GeoDefense Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 2196.Computer 树形dp 树的直径
Computer Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- 洛谷 P1352 没有上司的舞会【树形DP】(经典)
<题目链接> <转载于>>> > 题目描述: 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的 ...
- hdu 6201 【树形dp||SPFA最长路】
http://acm.hdu.edu.cn/showproblem.php?pid=6201 n个城市都在卖一种书,该书的价格在i城市为cost[i],商人打算从某个城市出发到另一个城市结束,途中可以 ...
- hdu 4081 最小生成树+树形dp
思路:直接先求一下最小生成树,然后用树形dp来求最优值.也就是两遍dfs. #include<iostream> #include<algorithm> #include< ...
- HDU 3899 简单树形DP
题意:一棵树,给出每个点的权值和每条边的长度, 点j到点i的代价为点j的权值乘以连接i和j的边的长度.求点x使得所有点到点x的代价最小,输出 虽然还是不太懂树形DP是什么意思,先把代码贴出来把. 这道 ...
- HDU 4044 GeoDefense
树形DP,和背包差不多.dp[now][x]表示now这个节点的子树上,花费为x的时候,获得的最大防御能力(保证敌方HP<=0) #include<cstdio> #include& ...
- HDU 4714 Tree2cycle (树形DP)
题意:给定一棵树,断开一条边或者接上一条边都要花费 1,问你花费最少把这棵树就成一个环. 析:树形DP,想一想,要想把一棵树变成一个环,那么就要把一些枝枝叶叶都换掉,对于一个分叉是大于等于2的我们一定 ...
随机推荐
- html5 滚动小球
<html> <head> <meta charset="utf-8"/> </head> <body onkeydown=& ...
- Levko and Array
题意: 有一长度为n的正整数序列,你可以选择K个数字任意改变它,使得$max \{ a(i+1) - a(i) \} $ 最小,求最小值. 解法: 1.$O(n^2log(MAX_A) )$,考虑二分 ...
- docker的安装与卸载
卸载老版本docker sudo apt-get remove docker docker-engine docker.io /var/lib/docker/目录下存放着 images, contai ...
- MFC中CArray类原理及其应用
1.CArray类应用 函数简介CArray::GetSize int GetSize( ) const;取得当前数组元素个数. CArray::GetUpperBound int GetUpperB ...
- [Xcode 实际操作]九、实用进阶-(10)定位设备的使用
目录:[Swift]Xcode实际操作 本文将演示定位设备的使用. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKit //导入需要用到的定位 ...
- JavaScript 原生提供两个 Base64 相关的方法
JavaScript 原生提供两个 Base64 相关的方法. btoa():任意值转为 Base64 编码 atob():Base64 编码转为原来的值 var string = 'Hello Wo ...
- .NET 基础 一步步 一幕幕 [.NET基础知识点]
.NET基础知识点 l .Net平台 .Net FrameWork框架 l .Net FrameWork框架提供了一个稳定的运行环境,:来保障我们.Net平台正常的运转 l 两种交 ...
- UWP 版本号
一:版本号 个人开发者对于版本号的命名相对随便一点,如果是大公司的话,命名则要规范一点.以开发UWP为例 在创建包的时候,开发者可以自定义版本号或者点击自动增加. 二:对应上图中的四个格子中的数字 第 ...
- 如何实现序列化为json
因为需要观察对象的数据,所以寻找能自动描述对象中字段名和其值的描述类,咨询了不少人,都推荐使用json,但是json使用起来有一点额外的操作. 需要在文件中引用 using System.Web.Sc ...
- ubuntu触摸板关闭开启
sudo rmmod psmouse #用来禁用触摸板 sudo modprobe psmouse #用来启用触摸板