内网 可怜与超市题解 树形dp+合并

调过了题比较高兴

首先想到了dp柿子 f[i][j][0/1]代表第i个节点买了j个用(1)没用(0)优惠券的最小花费。

而且是从子节点向父节点转移。

f[i][j][0]=min(f[k][l][0]+f[i][j-l][0]) k是i的儿子,l属于sz[i]。

f[i][j][1]=min(min(f[k][l][1],f[k][l][0])+f[i][j-l][1]) 同上。

然后暴力转移,发现是n3复杂度,最多T70(再次%%%有钱人用我的柿子暴力卡过)

有钱人的暴力方法:判断当前钱数是否超过了所带的钱数,超过根本无法转移。

其实这个卡常我也想到了但是没有打全因为懒话说打正解不是更麻烦么嘤嘤嘤

说一下正解

运用到了学长在写考试T2时的思想,也就是合并,具体证明参见skyh博客%%%%%

然后我们发现它也可以合并(估计学长就是想让我们练这个)

tmp数组1维滚动,2维代表用没用优惠券,3维代表买了几个 (两个半维)

先把自己加上去,sz++,然后tmp赋初值。

接下来枚举儿子,让当前大小j和儿子大小k共同去更新j+k,在更新完之后去加上儿子的大小

所以复杂度会从n3下降到n2,最后更新答案。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define ll long long
 5 using namespace std;
 6 int const maxn=5010;
 7 int const inf=0x3f3f3f3f;
 8 struct node{int to,nxt;}l[5010];
 9 int n,b,tot,head[maxn],c[maxn],d[maxn],fa[maxn],sz[maxn],f[maxn][maxn][2],ans,tmp[2][2][maxn];
10 void add(int x,int y)
11 {
12     l[++tot].to=y;
13     l[tot].nxt=head[x];
14     head[x]=tot;
15 }
16 void dfs(int x)
17 {
18     sz[x]=1;
19     for(int i=head[x];i;i=l[i].nxt)
20     {
21         dfs(l[i].to);
22         sz[x]+=sz[l[i].to];
23     }
24     for(int i=0;i<=sz[x];i++) f[x][i][0]=f[x][i][1]=inf;
25     if(sz[x]==1)
26     {
27         f[x][0][0]=0;f[x][1][0]=c[x];f[x][1][1]=c[x]-d[x];
28         return ;
29     }
30     memset(tmp,0x3f,sizeof(tmp));
31     int tm=0,size=1,cur=0;
32     tmp[0][0][0]=0;tmp[0][0][1]=c[x];tmp[0][1][1]=c[x]-d[x];
33     for(int i=head[x];i;i=l[i].nxt)
34     {
35         int y=l[i].to;tm++;
36         memset(tmp[cur^1],0x3f,sizeof(tmp[cur^1]));
37         for(int j=size;j>=0;j--)
38         {
39             for(int k=0;k<=sz[y];k++)
40             {
41                 tmp[cur^1][0][j+k]=min(tmp[cur^1][0][j+k],min(tmp[cur][0][j]+f[y][k][0],tmp[cur][0][j+k]));
42                 if(j!=0) tmp[cur^1][1][j+k]=min(tmp[cur^1][1][j+k],min(tmp[cur][1][j]+min(f[y][k][0],f[y][k][1]),tmp[cur][1][j+k]));
43             }
44         }
45         cur^=1;size+=sz[y];
46     }
47     for(int i=1;i<=sz[x];i++) f[x][i][0]=tmp[cur][0][i],f[x][i][1]=tmp[cur][1][i];
48 }
49 int main()
50 {
51     scanf("%d%d",&n,&b);
52     scanf("%d%d",&c[1],&d[1]);
53     memset(f,0x3f,sizeof(f));
54     for(int i=2;i<=n;i++)
55     {
56         scanf("%d%d%d",&c[i],&d[i],&fa[i]);
57         add(fa[i],i);
58     }
59     dfs(1);
60     for(int i=0;i<=n;i++)
61     {
62         if(f[1][i][0]<=b) ans=max(ans,i);
63         if(f[1][i][1]<=b) ans=max(ans,i);
64     }
65     printf("%d",ans);
66     return 0;
67 }

丑陋的代码

原文地址:https://www.cnblogs.com/MouDing/p/11192653.html

时间: 2024-07-30 22:09:21

内网 可怜与超市题解 树形dp+合并的相关文章

【bzoj1907】树的路径覆盖 树形dp

题目描述 输入 输出 样例输入 1 7 1 2 2 3 2 4 4 6 5 6 6 7 样例输出 3 题解 树形dp 设f[x]表示以x为根的子树完成路径覆盖,且x为某条路径的一端(可以向上延伸)的最小路径数,g[x]表示以x为根的子树完成路径覆盖,且x不为某条路径的一端的最小路径数. 那么考虑点x,只有三种情况:单独成路径.与一条子树的链成路径.与两条子树的链成路径. 这三种情况分别对应三种状态转移方程,具体见代码. 然而看到网上题解大把大把的贪心我也是醉了qaq #include <cstd

【bzoj3696】化合物 树形dp

题目描述 首长NOI惨跪,于是去念文化课了.现在,他面对一道化学题.这题的来源是因为在一个奇怪的学校两个化竞党在玩一个奇怪的博弈论游戏.这个游戏很蛋疼,我相信你们也没有兴趣听.由于这个游戏涉及博弈论,因此化竞的同学就要求首长求一个类似SG函数的值.他们手中有一种非常神奇的化合物,它的分子由N个原子组成(不要在意一个原子可能和及其多个原子成键这个细节).这个分子构成一个树结构,1号分子为根.    若两个原子i.j到它们的最近公共祖先的距离分别是Li和Lj,定义它们的Aij值为:Aij=Li  x

【bzoj3522】[Poi2014]Hotel 树形dp

题目描述 有一个树形结构的宾馆,n个房间,n-1条无向边,每条边的长度相同,任意两个房间可以相互到达.吉丽要给他的三个妹子各开(一个)房(间).三个妹子住的房间要互不相同(否则要打起来了),为了让吉丽满意,你需要让三个房间两两距离相同.有多少种方案能让吉丽满意? 输入 第一行一个数n.接下来n-1行,每行两个数x,y,表示x和y之间有一条边相连. 输出 让吉丽满意的方案数. 样例输入 7 1 2 5 7 2 5 2 3 5 6 4 5 样例输出 5 题解 树形dp 如果树上三个点之间两两距离相同

【bzoj1304】[CQOI2009]叶子的染色 树形dp

题目描述 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白色.你的着色方案应该保证根结点到每个叶子的简单路径上都至少包含一个有色结点(哪怕是这个叶子本身). 对于每个叶结点u,定义c[u]为从根结点从U的简单路径上最后一个有色结点的颜色.给出每个c[u]的值,设计着色方案,使得着色结点的个数尽量少. 输入 第一行包含两个正整数m, n,其中n是叶子的个数,m是结点总数.结点编号为1,2,…,m,其中编号1,2,… ,n是叶子.以下

题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)

写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换根法 作为一道不定根的树形DP,如果直接对每个点进行DP,可能时间会炸掉 但是,优秀的二次换根和扫描法可以再O(n^2)内解决问题. 二次扫描的含义:(来自lyd 算法竞赛进阶指南) 第一次扫描:任选一个节点为根节点(我会选1)在树上进行树形DP,在回溯时,从儿子节点向父节点(从底向上)进行状态转移

Vijos p1770 大内密探 树形DP+计数

4天终于做出来了,没错我就是这么蒟蒻.教训还是很多的. 建议大家以后编树形DP不要用记忆化搜索,回溯转移状态个人感觉更有条理性. 大神题解传送门 by iwtwiioi 我的题解大家可以看注释"//"部分 本题我用的树形DP中dp[x][fa][need]表示编号为x的节点的父亲选(1)没选(0),x的父亲需(1)不需要(0)其他节点来覆盖. 若父亲节点选了,则need肯定为0,所以不存在fa==1而need==1的状态,相当于浪费了¼的空间.毕竟数据范围比较小,而且程序要有可读性!程

树形 DP 总结

本文转自:http://blog.csdn.net/angon823/article/details/52334548 介绍 1.什么是树型动态规划 顾名思义,树型动态规划就是在"树"的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有二种方法既顺推与逆推,而树型动态规划是建立在树上的,所以也相应的有二个方向: 1.叶->根:在回溯的时候从叶子节点往上更新信息 2.根 - >叶:往往是在从叶往根d

NOIP2011pj表达式的值[树形DP 笛卡尔树]

题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算. 现给定一个未完成的表达式,例如+(*_),请你在横线处填入数字0 或者1 ,请问有多少种填法可以使得表达式的值为0 . 输入输出格式 输入格式: 输入文件名为exp.in ,共 2 行. 第1 行为一个整数 L,表示给定的表达式中除去横线外的运

【BZOJ1040】[ZJOI2008]骑士 树形DP

[BZOJ1040][ZJOI2008]骑士 Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶.骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾.每个骑士都有且仅有一个