dp杂题选做
题目其实挺简单的,难点在于状态的设计(其实也没多难)。
令 \(f_i\) 表示 \(i\) 个点的 \(m\) 叉树的数量,发现无法转移。设 \(g_{i,j}\) 表示根节点所在子树内有 \(i\) 个节点,\(j\) 个儿子(儿子所在子树可以为空)。可以写出转移方程:\(g_{i,j}=\sum\limits_{k=0}^{i-1} g_{i-k,j-1}\times f_k\),\(f_i=g_{i,m}\)
点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=200,mod=1e4+7;
int n,m,f[N][N];
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n),read(m);
for(int i=0;i<=m;i++){
f[1][i]=f[0][i]=1;
}
for(int i=2;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=0;k<i;k++){
f[i][j]=(f[i][j]+f[i-k][j-1]*f[k][m]%mod)%mod;
}
}
}
write_endl(f[n][m]);
return 0;
}
个人觉得这题非常神秘。
根据题目可知每次访问操作是访问完自己的子树,再访问父亲。所以除了第一次任意选点,剩下的都是从某个叶子节点跳到它的一个祖先或者往它的某棵子树跳。显然一颗子树对于后面的影响在于遍历完这颗子树后停在了哪里。
令 \(f_{u,x}\) 表示从根开始,访问完以 \(u\) 为根的子树后停在 \(x\) 处的最小费用,\(ls/rs\) 表示左/右儿子。分类讨论可以得到长得极为对称的两个转移方程
当 \(x\) 在左子树,\(f_{u,y}=\min\{dis(u,ls)\times a_{ls}+f_{ls,x}+dis(x,rs)\times a_{rs}+f_{rs,y}\}\)
当 \(x\) 在右子树,\(f_{u,y}=\min\{dis(u,rs)\times a_{rs}+f_{rs,x}+dis(x,ls)\times a_{ls}+f_{ls,y}\}\)
这个方程的复杂度接近 \(O(n^2)\),显然不能接受。
拆开式子,\(dis(x,rs)=dis(u,rs)+dis(x,u)\),发现只有 \(dis(x,u)\) 是个影响答案的关键信息,将它记录下来。
但因为没有要求从 \(1\) 开始,所以定义另一个状态 \(g_{u,x}\) 表示访问完以 \(u\) 为根的子树后停在 \(x\) 处的最小费用。继续分类讨论
当 \(x\) 在左子树,\(g_{u,y}=\min\{f_{u,y},f_{ls,x}+dis(x,u)\times a_u+dis(rs,u)\times a_{rs}+f_{rs,y}\}\)
当 \(x\) 在右子树,\(g_{u,y}=\min\{f_{u,y},f_{rs,x}+dis(x,u)\times a_u+dis(ls,u)\times a_{ls}+f_{ls,y}\}\),最后从所有 \(g_{1,x}\) 中取最小值即可。
点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
template<typename T>
inline void read(T &x){
x=0;
int f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+(ch-'0');
ch=getchar();
}
x=(f==1?x:-x);
}
template<typename T>
inline void write(T x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10){
write(x/10);
}
putchar(x%10+'0');
}
template<typename T>
inline void write_endl(T x){
write(x);
putchar('\n');
}
template<typename T>
inline void write_space(T x){
write(x);
putchar(' ');
}
}
using namespace IO;
const int N=2e5+10,inf=1e18;
int dis[N],n,a[N],b[N];
vector<int>d[N],f[N],g[N];
int ls(int p){
return p<<1;
}
int rs(int p){
return p<<1|1;
}
int fa(int p){
return p>>1;
}
void dfs(int u){
dis[u]=dis[fa(u)]+b[u];
if(ls(u)<=n){
dfs(ls(u));
int s=f[ls(u)].size();
if(rs(u)<=n){
dfs(rs(u));
int ans1=inf,ans2=inf,ansp1=inf,ansp2=inf;
for(int i=0;i<f[u].size();i++){
if(i<s){
ans1=min(ans1,f[ls(u)][i]+b[ls(u)]*a[ls(u)]+(d[u][i]+b[rs(u)])*a[rs(u)]);
ansp1=min(ansp1,g[ls(u)][i]+d[u][i]*a[u]+b[rs(u)]*a[rs(u)]);
}
else{
ans2=min(ans2,f[rs(u)][i-s]+b[rs(u)]*a[rs(u)]+(d[u][i]+b[ls(u)])*a[ls(u)]);
ansp2=min(ansp2,g[rs(u)][i-s]+d[u][i]*a[u]+b[ls(u)]*a[ls(u)]);
}
}
for(int i=0;i<f[u].size();i++){
if(i<s){
f[u][i]=ans2+f[ls(u)][i];
g[u][i]=min(f[u][i],ansp2+f[ls(u)][i]);
}
else{
f[u][i]=ans1+f[rs(u)][i-s];
g[u][i]=min(f[u][i],ansp1+f[rs(u)][i-s]);
}
}
}
else{
for(int i=u;i>=1;i/=2){
f[i].pb(0);
g[i].pb(0);
d[i].pb(dis[u]-dis[i]);
}
f[u][0]=b[ls(u)]*a[ls(u)];
g[u][0]=inf;
f[u][1]=inf;
g[u][1]=b[ls(u)]*a[u];
}
}
else{
for(int i=u;i>=1;i/=2){
f[i].pb(0);
g[i].pb(0);
d[i].pb(dis[u]-dis[i]);
}
}
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n);
for(int i=1;i<=n;i++){
read(a[i]);
}
for(int i=2;i<=n;i++){
read(b[i]);
}
dfs(1);
int ans=inf;
for(int i=0;i<g[1].size();i++){
ans=min(ans,g[1][i]);
}
write_endl(ans);
return 0;
}
dp杂题选做的更多相关文章
- 贪心/构造/DP 杂题选做Ⅱ
由于换了台电脑,而我的贪心 & 构造能力依然很拉跨,所以决定再开一个坑( 前传: 贪心/构造/DP 杂题选做 u1s1 我预感还有Ⅲ(欸,这不是我在多项式Ⅱ中说过的原话吗) 24. P5912 ...
- 贪心/构造/DP 杂题选做Ⅲ
颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...
- 贪心/构造/DP 杂题选做
本博客将会收录一些贪心/构造的我认为较有价值的题目,这样可以有效的避免日后碰到 P7115 或者 P7915 这样的题就束手无策进而垫底的情况/dk 某些题目虽然跟贪心关系不大,但是在 CF 上有个 ...
- 期望dp好题选做
前言: 最近连考两场期望dp的题目,sir说十分板子的题目我竟然一点也不会,而且讲过以后也觉得很不可改.于是开个坑. 1.晚测10 T2 大佬(kat) 明明有\(O(mlog)\)的写法,但是\(m ...
- dp杂题(根据个人进度选更)
----19.7.30 今天又开了一个新专题,dp杂题,我依旧按照之前一样,这一个专题更在一起,根据个人进度选更题目; dp就是动态规划,本人认为,动态规划的核心就是dp状态的设立以及dp转移方程的推 ...
- 正睿OI DAY3 杂题选讲
正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...
- 2019暑期金华集训 Day6 杂题选讲
自闭集训 Day6 杂题选讲 CF round 469 E 发现一个数不可能取两次,因为1,1不如1,2. 发现不可能选一个数的正负,因为1,-1不如1,-2. hihoCoder挑战赛29 D 设\ ...
- Atcoder 水题选做
为什么是水题选做呢?因为我只会水题啊 ( 为什么是$Atcoder$呢?因为暑假学长来讲课的时候讲了三件事:不要用洛谷,不要用dev-c++,不要用单步调试.$bzoj$太难了,$Topcoder$整 ...
- [SDOI2016]部分题选做
听说SDOI蛮简单的,但是SD蛮强的.. 之所以是选做,是因为自己某些知识水平还不到位,而且目前联赛在即,不好花时间去学sa啊之类的.. bzoj4513储能表&bzoj4514数字配对 已写 ...
- 【做题记录】DP 杂题
P2577 [ZJOI2004]午餐 $\texttt{solution}$ 想到贪心: 吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 状态: \(f[i][j]\) 表示前 \(i\ ...
随机推荐
- (瞎学系列)RISC-V & ARM & x86
reduced instruction set computing (RISC) -> ARM & RISC-V complex instruction set computing (C ...
- mymath.so共享库
共享库的使用(.so)文件 1.共享库的概念 2.创建共享库命令 # 1.将.c生成.o文件,(生成与位置无关的代码-fPIC)gcc -c add.c -o add.o -fPIC # 2.使用 ...
- 后端006_登录之后返回Token
现在开始我们就可以写登录相关的东西了.首先登录相关的流程是这样的,前端输入用户和密码传给后端,后端判断用户名和密码是否正确,若正确,则生成JWT令牌,若不正确,则需要让前端重新输入,前端如果拿到了JW ...
- [vue2 + jointjs + svg-pan-zoom] 节点自动布局渲染 + 拖拽缩放
启动vue项目,执行以下命令安装dagre.graphlib.jointjs.svg-pan-zoom. npm install dagre graphlib jointjs svg-pan-zoom ...
- windows中使用jenkins部署项目,后端无法启动问题
忙活一下午+一上午,问题终于解决了.找了各种办法,最终解决方式如下: 1.jenkins打包成功,到接口会报502异常 原因:后端未成功启动 解决办法: 1.刚开始使用shell命令,无法查杀进程,后 ...
- Shiro权限管理框架-@RequiresPermissions 注解 使用问题记录
背景: 需要在springboot项目里面用到shiro的权限管理,Shiro访问控制流程:先shiro认证(登录时调用) 然后 shiro授权,但是项目里面登录的功能用的公司统一的系统,所以需要&q ...
- win10_pyhive链接hive失败,提示:Could not start SASL
win10_pyhive链接hive失败,提示:Could not start SASL https://blog.csdn.net/weixin_45684985/article/details/1 ...
- PO、VO、DAO、BO、DTO、POJO 之间的区别
PO(Persistant Object),持久对象 这个对象是与数据库中的表相映射的Java对象. VO(Value Object),值对象 通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据 ...
- LeetCode 周赛 336,多少人直接 CV?
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 今天早上是 LeetCode 第 336 场周赛,你参加了吗?这场周赛整体质量比较高,但 ...
- 【RSocket】使用 RSocket(三)——服务端主动调用客户端方法
1. 编写客户端接收请求的逻辑 我们可以在初始化 Rsocket 实例的时候指定客户端可以被调用的方法,使用 acceptor() 指定可被调用的方法和方法使用的通信模型类型: 通信类型为 Reque ...