树形dp
来源:互联网 发布:2007版excel数据有效性 编辑:程序博客网 时间:2024/06/10 07:06
没时间写先记下思路
f(x)
g(x)
分别记录父亲节点选和不选的情况
• 最大独立集
• 最大匹配
• 最小覆盖
• 最小支配
• *带权的上述问题模型
据说• 最大独立集和• 最大匹配互为补集
最大独立集与 最小覆盖 相同
BZOJ 1040
• 给定环套树,求带权最大独立集(我抠不出来环的放弃了)
IOI 2005 river
• 给定 n 个点的有根树
• 每条边有权,每个点有权值 w
• 你要在 k 个点上建立伐木场
• 对于每个没有建伐木场的点 x,令与它最近的、有伐⽊木场的
点为 y,你需要支付 dis(x,y) * w[x] 的代价
• 选择合适的位置建伐木场,最小化总代价
• n <= 100
首先先来分析一下标程
#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<algorithm>#define maxn 105#define inf 1061109567using namespace std;char ch;int n,k,a,b,c,tot,w[maxn],now[maxn],son[maxn],pre[maxn],val[maxn];int dist[maxn],f[maxn][maxn][maxn],tmp[maxn][maxn][maxn];bool ok,bo[maxn][maxn];void read(int &x){ for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); if (ok) x=-x;}void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}int turn(int x){if (x==inf) return 0;return x;}void dfs(int u,int last){ if (bo[u][last]) return; bo[u][last]=1; for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]){ dist[v]=dist[u]+val[p]; dfs(v,last),dfs(v,v); for (int i=0;i<=k;i++){ f[u][last][i]=inf; for (int j=0;j<=i;j++){ if (i>j) f[u][last][i]=min(f[u][last][i],tmp[u][last][i-j-1]+f[v][v][j]); f[u][last][i]=min(f[u][last][i],tmp[u][last][i-j]+f[v][last][j]+w[v]*(dist[v]-dist[last])); } } memcpy(tmp[u][last],f[u][last],sizeof(tmp[u][last])); }}int main(){ read(n),read(k); for (int i=1;i<=n;i++) read(w[i]),read(b),read(c),put(b,i,c); dfs(0,0); printf("%d\n",f[0][0][k]); return 0;}
看起来csdn的页面不够宽(滑稽)
这种题还是以后再看。
月考彻底崩盘后的夜晚。
和Visit_world畅聊一晚惊觉自己好弱
于是抄了一发黄学长的代码
可能理解不是很深刻,但是有了一个初步的理解
主要思路
建树
状态:基础部件-》直接有几个来几个,类似背包问题;
高级部件-》用基础部件转移;
由于形似背包且是树形dp
我们不妨f[i][j][k]表示第I个物品用j件合成子树花费为k的最大力量值
设P[x],L[x],M[x],表示物品x的能量,购买上限与价格
L[x]=min(L[x],m/M[x])
高级装备的M和L随便dp一下
再用f[i][j][k]表示第i个物品,有j件用于上层的合成,花费金钱是k所能获得的最大力量
对于以x为根的子树,枚举合成 l 个 x 物品,然后再用其余的钱买一些 x 子树内的装备不用于合成
枚举合成物品数量 l ,用g[i][j]表示x的前i个儿子的子树,花费j的钱,所能获得的最大力量
g[tot][j]=max{g[tot-1][j-k]+f[e[i].to][l*e[i].v][k]}
//e[i].to是儿子结点,e[i].v是所需数量,就是从j中拿出k的钱在e[i].to的子树内购买
最后再枚举合成的 l 个 x 物品中有 j 个是直接用于增加力量,剩余用于合成的
f[x][j][k]=max{g[tot][k]+P[x]*(l-j)}
最后我们暴力记录结果
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cstdlib>#include<cmath>using namespace std;int n,m,cnt,ans,tot;const int inf=1000000000;#define ll long longint p[55],l[55],M[55];int g[55][2005],f[55][105][2005];int h[55][2005];char ch[5];int deg[55],last[55];int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f;}struct data{ int to,next,v;}e[20005];void insert(int u,int v,int w){ e[++cnt].to=v; e[cnt].next=last[u]; last[u]=cnt;e[cnt].v=w; deg[v]++;}void dp(int x){ if(!last[x]){ l[x]=min(l[x],m/M[x]); for(int i=0;i<=l[x];i++) for(int j=i;j<=l[x];j++) f[x][i][j*M[x]]=(j-i)*p[x]; return ; } l[x]=inf; for(int i=last[x];i;i=e[i].next){ dp(e[i].to); l[x]=min(l[x],l[e[i].to]/e[i].v); M[x]+=e[i].v*M[e[i].to]; } l[x]=min(l[x],m/M[x]); memset(g,-0x3f3f3f3f,sizeof(g)); g[0][0]=0; for(int L=l[x];L>=0;L--){ int tot=0; for(int i=last[x];i;i=e[i].next){ tot++; for(int j=0;j<=m;j++) for(int k=0;k<=j;k++) g[tot][j]=max(g[tot][j],g[tot-1][j-k]+f[e[i].to][L*e[i].v][k]); } for(int j=0;j<=L;j++) for(int k=0;k<=m;k++) f[x][j][k]=max(f[x][j][k],g[tot][k]+p[x]*(L-j)); }} int main(){ memset(f,-0x3f3f3f3f,sizeof(f)); n=read();m=read(); for(int i=1;i<=n;i++){ p[i]=read(); scanf("%s",ch); if(ch[0]=='A'){ int x=read(); while(x--){ int v=read(),num=read(); insert(i,v,num); } } else M[i]=read(),l[i]=read(); } for(int x=1;x<=n;x++){ if(!deg[x]){ dp(x); tot++; for(int i=0;i<=m;i++) for(int j=0;j<=i;j++) for(int k=0;k<=l[x];k++) h[tot][i]=max(h[tot][i],h[tot-1][j]+f[x][k][i-j]); } } for(int i=0;i<=m;i++) ans=max(ans,h[tot][i]); printf("%d\n",ans); return 0;}
不错的结果
月考炸了
但是发现VWdalao强的飞起
真的是一年自学无敌
我真是菜
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形DP
- 树形DP
- 树形DP
- 树形dp
- 树形dp
- 树形dp
- 树形dp
- 树形DP
- 树形DP
- 树形DP
- 树形DP
- 树形dp
- C++内存管理
- 大数——大数加法
- owl-carousel2轮播图插件
- 计算机视觉入门笔记
- 初识.net界面程序(6)——类及其属性和方法的实现练习
- 树形dp
- hasmap源码分析(jdk1.8)
- linux 使用hadoop中常用的一些命令
- Android学习笔记(一)---工具篇
- PIGS POJ
- 在Sblime Text 3中编译运行java 默认环境已配置好
- 为何Neural Network的Node要用Sigmoid Function?
- 最近总结
- 欢迎使用CSDN-markdown编辑器