题目:https://www.luogu.org/problemnew/show/P3354

虽说是几个月前曾经讲过的题,但没有题解而自己(花了两个多小时)A了好高兴!!!

这是一个很好的套路:“承诺”以算值。

  伐木场放在哪里对于节点的值是有影响的,所以自然的思路就是把和该节点有关的伐木场位置也压进状态里,对于不同的状态算出不同的值;

    也就是“承诺”那些伐木场会放在哪里。

  相同的承诺之间才能转移。

这样就有了一个问题:该节点的“承诺”记录的是该节点上方的下一个伐木场在哪;但是该节点放不放伐木场对于转移也有影响。

  试图用“承诺下一个伐木场在0”表示该节点放伐木场,但是有诸多不对劲;比如根据定义,0处承诺了的话,上面就没有“下一个伐木场的位置”了,导致无法转移之类;

  然后终于想到可以再开一维状态0/1表示该节点到底放没放伐木场!这样一下就变得通顺又简单!

树形DP的坑点:那个 j 的倒序!仔细一看转移需要用到同层的小一些的 j 的。

        还有常规的看看siz等等。

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=;const ll INF=0x7fffffff;
int n,m,head[N],fa[N],xnt,siz[N],len[N];
ll a[N],c[N][N],ed[N],dp[N][][N][];
struct Edge{
int next,to;ll w;
Edge(int n=,int t=,ll w=):next(n),to(t),w(w) {}
}edge[N<<];
void init(int cr,ll dis,int cnt,int nw)
{
c[cr][cnt]=dis*a[cr];if(cnt)dp[cr][][cnt][]=c[cr][cnt];
if(!nw)
{
len[cr]=cnt;return;
}
init(cr,dis+ed[nw],cnt+,fa[nw]);
}
void dfs(int cr)
{
siz[cr]=;for(int j=;j<=n;j++)dp[cr][j][][]=;
for(int k=;k<=len[cr];k++)dp[cr][][k][]=;
for(int i=head[cr],v;i;i=edge[i].next)
{
dfs(v=edge[i].to);
for(int j=min(m,siz[cr]+siz[v]);j>=;j--)//
{
for(int k=;k<=len[cr];k++)
{
dp[cr][j][k][]+=min(dp[v][][][],dp[v][][][]);
dp[cr][j][k][]+=min(dp[v][][k+][],dp[v][][k+][]);
// printf("dp[%d][%d][%d]=%lld dp[%d][%d][%d]=%lld\n"
// ,cr,j,k,dp[cr][j][k],v,0,k+1,dp[v][0][k+1]);
for(int l=max(,j-siz[cr]);l<=j&&l<=siz[v];l++)
dp[cr][j][k][]=min(dp[cr][j][k][],dp[cr][j-l][k][]+min(dp[v][l][k+][],dp[v][l][k+][])),
dp[cr][j][k][]=min(dp[cr][j][k][],dp[cr][j-l][k][]+min(dp[v][l][][],dp[v][l][][]));
// printf("dp[%d][%d][%d][0]=%lld dp[%d][%d][%d][0]=%lld\ndp[%d][%d][%d][0]=%lld dp[%d][%d][%d][1]=%lld\n"
// ,cr,j,k,dp[cr][j][k][0],cr,j-l,k,dp[cr][j-l][k][0],v,l,k+1,dp[v][l][k+1][0],v,l,k+1,dp[v][l][k+1][1]),
// printf("dp[%d][%d][%d][1]=%lld dp[%d][%d][%d][1]=%lld\ndp[%d][%d][%d][0]=%lld dp[%d][%d][%d][1]=%lld\n\n"
// ,cr,j,k,dp[cr][j][k][1],cr,j-l,k,dp[cr][j-l][k][1],v,l,k+1,dp[v][l][k+1][0],v,l,k+1,dp[v][l][k+1][1]);
}
}
siz[cr]+=siz[v];
}
}
int main()
{
scanf("%d%d",&n,&m);int x;ll z;
for(int i=;i<=n;i++)
{
scanf("%lld%d%lld",&a[i],&x,&z);
edge[++xnt]=Edge(head[x],i,z);head[x]=xnt;
fa[i]=x;ed[i]=z;
}
memset(dp,,sizeof dp);dp[][][][]=;
for(int i=;i<=n;i++)init(i,,,i);
dfs();
printf("%lld",dp[][m][][]);
return ;
}

洛谷3354(IOI2005)河流——“承诺”的更多相关文章

  1. 洛谷P3354 [IOI2005]Riv 河流——“承诺”DP

    题目:https://www.luogu.org/problemnew/show/P3354 状态中要记录一个“承诺”,只需相同承诺之间相互转移即可: 然后就是树形DP的套路了. 代码如下: #inc ...

  2. 洛谷P3354 Riv河流 [IOI2005] 树型dp

    正解:树型dp 解题报告: 传送门! 简要题意:有棵树,每个节点有个权值w,要求选k个节点,最大化∑dis*w,其中如果某个节点到根的路径上选了别的节点,dis指的是到达那个节点的距离 首先这个一看就 ...

  3. 3354 [IOI2005]河流

    题目描述 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄——名叫 ...

  4. IOI 2005 River (洛谷 3354)

    题目描述 几乎整个Byteland王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海.这条大河的入海口处有一个村庄--名叫 ...

  5. 洛谷 P1546 最短网络 Agri-Net

    题目链接 https://www.luogu.org/problemnew/show/P1546 题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当 ...

  6. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  7. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  8. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  9. 洛谷 P2701 [USACO5.3]巨大的牛棚Big Barn Label:二维数组前缀和 你够了 这次我用DP

    题目背景 (USACO 5.3.4) 题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N ...

随机推荐

  1. 搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法

    搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法 2PC 由于BASE理论需要在一致性和可用性方面做出权衡,因此涌现了很多关于一致性的算法和协议.其中比较著名的有二阶提交协议(2 Phas ...

  2. 重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系

    重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系 Innodb中的事务隔离级别和锁的关系 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁 ...

  3. C#学习历程(九)[类的定义与声明]

    一.C#中类的声明 在C#中必须先声明类,然后才能在程序中使用. 类的声明格式如下: [类的属性] [访问修饰符] class 类名称 [: 父类名]{    [成员修饰符] 类的成员变量或者成员函数 ...

  4. C#中使用GUID

    GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成GUID的API.生成算法很有意思,用到了以太网卡地址.纳秒级时间.芯片ID码和许多可 ...

  5. hdu2732

    题解: 和上一题差不多 然后注意格式 代码: #include<cstdio> #include<cmath> #include<algorithm> #inclu ...

  6. LeetCode OJ:Regular Expression Matching(正则表达式匹配)

    Implement regular expression matching with support for '.' and '*'. '.' Matches any single character ...

  7. qml 与C++交互

    最近一直在研究qml 怎么与C++交互,今天在网上看到一段代码忽然想明白了,哦!!!我在QT还只是一个小白,嘿嘿 首先在我们定义了CPP文件起名:比如:util.cpp,baidumusic.cpp ...

  8. C++中几个值得分析的小问题(1)

    下面3个小问题都是我认为C++ Beginner应该能够解答或辨别清楚的.希望我们能通过题目挖掘更多的信息,而不仅仅局限在解题.我最喜欢说的话:能力有限,所以作为抛砖引玉,希望共同讨论,指出错误. 另 ...

  9. DataTable和实体类通过反射相互转换

    using System.Runtime.Serialization; using System.Data; using System.Reflection; using System.Collect ...

  10. Linux:减号(-)详解

    减号(-) 代表标准输出/标准输入, 视命令而定. “-”代替stdin和stdout的用法 为应用程序指定参数 ps -aux tar -zxf test.tar 一个减号和两个减号 一个减号后面跟 ...