分组背包+树形DP(BY LPX)
来源:互联网 发布:淘宝怎么修改商品类目 编辑:程序博客网 时间:2024/05/15 19:00
专题传送门:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=24217#overview
A.POJ 1155
/*类型:树形DP题意:广播一场比赛,有发射站和用户,用户为叶子节点。每个发射站有消耗,到达用户有收益,现在问在不赔钱的情况下怎样使用户最大思路:dp[i][j] 为给第i个节点分配k个用户的收益(可以为负),显然使dp[1][j]为正的最大j为所求*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<string>#include<map>#include<queue>#include<vector>#include<algorithm>#define maxn 3100#define maxm 1100#define INF (1 << 28)#define TP int#define LL long long#define DB double#define Mid(x) ((x) >> 1)#define Lc(x) ((x) << 1)#define Rc(x) (((x) << 1)|1)#define Clear(a,b) memset(a,b,sizeof(a))using namespace std;inline TP Max(TP a,TP b){ if (a > b) return a; return b;}inline TP Min(TP a,TP b){ if (a > b) return b; return a;}bool cmp(TP a,TP b){ return a < b;}//BEGINstruct EDGE{ int v,w; };bool cmp1(EDGE a,EDGE b){ return a.w > b.w;}int dp[maxn][maxn], val[maxn], son[maxn];vector <EDGE> links[maxn];int dfs1(int k){ int i,mm; mm = links[k].size(); if (mm == 0) son[k] = 1; else son[k] = 0; for(i = 0;i < mm;i++) son[k] += dfs1(links[k][i].v); return son[k];}void dfs2(int k){ //printf("%dxxx\n",k); int mm = links[k].size(), i,ii,jj,now_limt = 0; dp[k][0] = 0; if (mm == 0) { dp[k][1] = val[k]; } for(i = 0;i < mm;i++) dfs2(links[k][i].v); for(i = 0;i < mm;i++) //分组背包,枚举组 for(ii = (now_limt += son[links[k][i].v]);ii >= 1;ii--) for(jj = 1;jj <= ii && jj <= son[links[k][i].v];jj++) dp[k][ii] = Max(dp[k][ii],dp[k][ii-jj] + dp[links[k][i].v][jj] - links[k][i].w); // //printf("%d:\n",k);for(i = 1;i <= son[k];i++) printf("%d ",dp[k][i]);printf("\n"); return ;}int Work(){ int n,m,tran,i,j,t; EDGE tmp; scanf("%d%d",&n,&m); for(i = 0;i < maxn;i++) for(j = 0;j < maxn;j++) dp[i][j] = -INF; Clear(son,0); tran = n - m; for(i = 1;i <= tran;i++) { scanf("%d",&t); for(j = 1;j <= t;j++){ scanf("%d%d",&tmp.v,&tmp.w); links[i].push_back(tmp); } //sort(links[i].begin(),links[i].end(),cmp1); } for(;i <= n;i++) scanf("%d",&val[i]); dfs1(1); //第一遍DFS统计每个点的子树的点数 //for(i = 1;i <= n;i++) // printf("%d_%d\n",i,son[i]); dfs2(1); //第二遍DFS开始DP // for(i = 1;i <= m;i++) // printf("%d %d\n",i,dp[1][i]); int ans = m; while(dp[1][ans] < 0) ans--; printf("%d\n",ans); return 0;}int main(){ //freopen("test.in","r",stdin); Work(); return 0;}
B.HDU 1011
/*类型:树形DP题意:一个虫子巢穴为树形结构,每个房间都有一些虫子和一定的概率存在脑虫。现在给你一定的战士,1战士可以消灭20个虫子,让你使打到脑虫的可能性最大思路:dp[i][j]代表打i子树要j战士时的最大可能*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<string>#include<map>#include<queue>#include<vector>#include<algorithm>#define maxn 210#define maxm 110#define INF (1 << 28)#define TP int#define LL long long#define DB double#define Mid(x) ((x) >> 1)#define Lc(x) ((x) << 1)#define Rc(x) (((x) << 1)|1)#define Clear(a,b) memset(a,b,sizeof(a))using namespace std;inline TP Max(TP a,TP b){ if (a > b) return a; return b;}inline TP Min(TP a,TP b){ if (a > b) return b; return a;}bool cmp(TP a,TP b){ return a < b;}//BEGINint m;int dp[maxn][maxn],bug[maxn],sum_bug[maxn],boss[maxn];vector <int> edge[maxn];void dfs2(int k,int fa){ //printf("%d\n",k); int mm = edge[k].size(),i,ii,jj; for(i = 0;i < mm;i++) if (edge[k][i] != fa) dfs2(edge[k][i],k); //if ((mm == 1 && fa > 0) || mm == 0) // if (bug[k] <= m) dp[k][bug[k]] = boss[k]; for(i = bug[k];i <= m;i++) dp[k][i] = boss[k]; for(i = 0;i < mm;i++) if (edge[k][i] != fa){ for(ii = m;ii >= bug[k];ii--) for(jj = 1;jj <= ii-bug[k];jj++) dp[k][ii] = Max(dp[k][ii],dp[k][ii-jj] + dp[edge[k][i]][jj]); } //printf("%d: %d\n",k,boss[k]); //for(i = 0;i <= sum_bug[k];i++) printf("%d ",dp[k][i]);printf("\n"); return ;}int Work(){ int n,i,tmp_u,tmp_v; scanf("%d%d",&n,&m); if (n == -1) return 0; for(i = 1;i <= n;i++) edge[i].clear(); Clear(dp,0); Clear(sum_bug,0); Clear(bug,0); for(i = 1;i <= n;i++) scanf("%d%d",&bug[i],&boss[i]),bug[i] = (bug[i] + 19) / 20; //for(i = 1;i <= n;i++) printf("%d ",bug[i]);printf("\n"); for(i = 1;i < n;i++){ scanf("%d%d",&tmp_u,&tmp_v); edge[tmp_u].push_back(tmp_v); edge[tmp_v].push_back(tmp_u); } if (m == 0) { printf("0\n"); return 1; } dfs2(1,0); printf("%d\n",dp[1][m]); return 1;}int main(){ //freopen("test.in","r",stdin); while(Work()); return 0;}//END
C.POJ 1947
/*类型:树形DP题意:给出一棵树,问最少切断几条边可以得到有p个结点的子树思路:dp[i][j]代表第i个点为根的子树要得到j个节点的子树最少切多少个边*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<string>#include<map>#include<queue>#include<vector>#include<algorithm>#define maxn 200#define maxm 1100#define INF (1000000)#define TP int#define LL long long#define DB double#define Mid(x) ((x) >> 1)#define Lc(x) ((x) << 1)#define Rc(x) (((x) << 1)|1)#define Clear(a,b) memset(a,b,sizeof(a))using namespace std;inline TP Max(TP a,TP b){ if (a > b) return a; return b;}inline TP Min(TP a,TP b){ if (a > b) return b; return a;}bool cmp(TP a,TP b){ return a < b;}//BEGINint p,ans;int dp[maxn][maxn];vector <int> edge[maxn];void dfs(int k){ int mm = edge[k].size(), i,ii,jj; if (k == 1) dp[k][1] = mm; else dp[k][1] = mm + 1; dp[k][0] = 1; for(i = 0;i < mm;i++) { dfs(edge[k][i]); for(ii = p;ii >= 1;ii--) for(jj = 1;jj <= ii-1;jj++) dp[k][ii] = Min(dp[k][ii],dp[k][ii-jj] + dp[edge[k][i]][jj] - 2); } //printf("%3d:",k);for(i = 0;i <= p;i++) printf("%9d",dp[k][i]);printf("\n"); if (dp[k][p] < ans) ans = dp[k][p]; return ;}int Work(){ int n,i,fa,son,j; scanf("%d%d",&n,&p); for(i = 0;i <= n;i++) for(j = 0;j <= p;j++) dp[i][j] = INF; for(i = 1;i < n;i++) { scanf("%d%d",&fa,&son); edge[fa].push_back(son); } ans = INF; dfs(1); printf("%d\n",ans); return 0;}int main(){ //freopen("test.in","r",stdin); Work(); return 0;}//END
D.HDU 1561
/*类型:树形DP题意:取M个城堡,使那啥最大思路:不说了,桑心*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<string>#include<map>#include<queue>#include<vector>#include<algorithm>#define maxn 250#define maxm 1100#define INF (1 << 28)#define TP int#define LL long long#define DB double#define Mid(x) ((x) >> 1)#define Lc(x) ((x) << 1)#define Rc(x) (((x) << 1)|1)#define Clear(a,b) memset(a,b,sizeof(a))using namespace std;inline TP Max(TP a,TP b){ if (a > b) return a; return b;}inline TP Min(TP a,TP b){ if (a > b) return b; return a;}bool cmp(TP a,TP b){ return a < b;}//BEGINint n,m;int dp[maxn][maxn],val[maxn];vector <int> son[maxn];void dfs(int k){ int mm = son[k].size(), i,ii,jj; dp[k][1] = val[k]; for(i = 0;i < mm;i++) { dfs(son[k][i]); for(ii = m;ii >= 1;ii--) for(jj = 0;jj <= ii-1;jj++) dp[k][ii] = Max(dp[k][ii],dp[k][ii-jj] + dp[son[k][i]][jj]); } //printf("%d: ",k);for(i = 0;i <= n;i++) printf("%d ",dp[k][i]);printf("\n"); return ;}int Work(){ int a,b,i; scanf("%d%d",&n,&m); if (n == 0) return 0; m++; Clear(dp,0); Clear(val,0); for(i = 0;i <= n;i++) son[i].clear(); for(i= 1;i <= n;i++){ scanf("%d%d",&a,&val[i]); son[a].push_back(i); } //for(i = 1;i <= n;i++) printf("%d ",val[i]);printf("\n"); dfs(0); printf("%d\n",dp[0][m]); return 1;}int main(){ // freopen("test.in","r",stdin); while(Work()); return 0;}//END
E.HDU 1561
/*类型:树形DP题意:给出一棵树,投放K个机器人,问使全部点都被走过的情况下机器人走的总路程和最小。思路:dp[i][j]代表第i个点为根的子树要得到j个节点的子树最少切多少个边*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<string>#include<map>#include<queue>#include<vector>#include<algorithm>#define maxn 11000#define maxm 12#define INF (1 << 28)#define TP int#define LL long long#define DB double#define Mid(x) ((x) >> 1)#define Lc(x) ((x) << 1)#define Rc(x) (((x) << 1)|1)#define Clear(a,b) memset(a,b,sizeof(a))using namespace std;inline TP Max(TP a,TP b){ if (a > b) return a; return b;}inline TP Min(TP a,TP b){ if (a > b) return b; return a;}bool cmp(TP a,TP b){ return a < b;}//BEGINstruct EDGE{ int ed,w; } tmp;int n,k;int dp[maxn][maxm];vector <EDGE> edge[maxn];void dfs(int now,int fa){ int mm = edge[now].size(), i,ii,jj,next; for(i = 0;i < mm;i++) if (edge[now][i].ed != fa) { next = edge[now][i].ed; dfs(next,now); for(ii = k;ii >= 0;ii--) { dp[now][ii] += dp[next][0] + edge[now][i].w * 2; for(jj = 0;jj <= ii;jj++) dp[now][ii] = Min(dp[now][ii],dp[now][ii-jj] + dp[next][jj] + edge[now][i].w * jj); } } return ;}int Work(){ int i,j,s,u,v,w; if (scanf("%d%d%d",&n,&s,&k) == EOF) return 0; for(i = 1;i <= n;i++) edge[i].clear(); Clear(dp,0); for(i = 1;i < n;i++) { scanf("%d%d%d",&u,&v,&w); tmp.w = w; tmp.ed = v; edge[u].push_back(tmp); tmp.ed = u; edge[v].push_back(tmp); } dfs(s,0); printf("%d\n",dp[s][k]); return 1;}int main(){ //freopen("test.in","r",stdin); while(Work()); return 0;}
F. POJ 2486
/*树形DP题意:一颗树上吃苹果,每个点上都有一定的苹果思路:状态dp[i][j][k]表示为第i个点走j步,k为0代表不回,k为1代表回则有三种转移,见代码。*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<string>#include<map>#include<queue>#include<vector>#include<algorithm>#include<math.h>#define maxn 110#define maxm 210#define INF (1 << 28)#define TP int#define LL long long#define DB double#define Mid(x) ((x) >> 1)#define Lc(x) ((x) << 1)#define Rc(x) (((x) << 1)|1)#define Clear(a,b) memset(a,b,sizeof(a))using namespace std;inline TP Max(TP a,TP b){ if (a > b) return a; return b;}inline TP Min(TP a,TP b){ if (a > b) return b; return a;}bool cmp(TP a,TP b){ return a < b;}//BEGINint k,n;int apple[maxn], dp[maxn][maxm][2];vector<int>edge[maxn];void dfs(int x,int fa){ int mm,i,j,jj,son; //0-不回 1-回 mm = edge[x].size(); for(i = 0;i < mm;i++) if (edge[x][i] != fa) dfs(edge[x][i],x); for (j = 0;j <= k;j++) dp[x][j][1] = dp[x][j][0] = apple[x]; for(i = 0;i < mm;i++) if ((son = edge[x][i]) != fa) for(j = k;j >= 0;j--) //又他妈傻逼了!!!!!! for(jj = 0;jj <= j;jj++) { if (jj >= 2) dp[x][j][0] = Max(dp[x][j][0],dp[x][j-jj][0]+dp[son][jj-2][1]); if (jj >= 1) dp[x][j][0] = Max(dp[x][j][0],dp[x][j-jj][1]+dp[son][jj-1][0]); if (jj >= 2) dp[x][j][1] = Max(dp[x][j][1],dp[x][j-jj][1]+dp[son][jj-2][1]); } return ;}int Work(){ int i,u,v; if (scanf("%d%d",&n,&k) == EOF) return 0; Clear(dp,0); Clear(apple,0); for(i = 1;i <= n;i++) scanf("%d",&apple[i]); for(i = 1;i <= n;i++) edge[i].clear(); for(i = 1;i < n;i++) { scanf("%d%d",&u,&v); edge[u].push_back(v); edge[v].push_back(u); } dfs(1,0); printf("%d\n",dp[1][k][0]);}int main(){ //freopen("test.in","r",stdin); while(Work()); return 0;}//END
J.HDU 4276
/*树形DP题意:思路:*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<string>#include<map>#include<queue>#include<vector>#include<algorithm>#include<math.h>#define maxn 110#define maxm 510#define OO (1 << 28)#define TP int#define LL long long#define DB double#define Mid(x) ((x) >> 1)#define Lc(x) ((x) << 1)#define Rc(x) (((x) << 1)|1)#define Clear(a,b) memset(a,b,sizeof(a))using namespace std;inline TP Max(TP a,TP b){ if (a > b) return a; return b;}inline TP Min(TP a,TP b){ if (a > b) return b; return a;}bool cmp(TP a,TP b){ return a < b;}//BEGINstruct EDGE{ int ed,cost; } tmp;vector<EDGE>edge[maxn];int n,t;int dp[maxn][maxm],gold[maxn];int dfs_find(int now,int fa){ int mm,i,time; if (now == n) return 0; mm = edge[now].size(); for(i = 0;i < mm;i++) if (edge[now][i].ed != fa) { time = dfs_find(edge[now][i].ed,now) + edge[now][i].cost; if (time >= 0) { edge[now][i].cost = 0; return time; } } return -OO;}void dfs(int now,int fa){ int mm,i,son,cost,j,jj; mm = edge[now].size(); for(j = 0;j <= t;j++) dp[now][j] = gold[now]; for(i = 0;i < mm;i++) if (edge[now][i].ed != fa) { son = edge[now][i].ed; dfs(son,now); cost = edge[now][i].cost; for(j = t;j >= 0;j--) for(jj = cost*2;jj <= j;jj++) dp[now][j] = Max(dp[now][j] , dp[now][j-jj] + dp[son][jj-cost*2]); } return ;}int Work(){ int i,u,v,w; if (scanf("%d%d",&n,&t) == EOF) return 0; Clear(dp,0); Clear(gold,0); for(i = 1;i <= n;i++) edge[i].clear(); for(i = 1;i < n;i++) { scanf("%d%d%d",&u,&v,&w); tmp.cost = w; tmp.ed = u; edge[v].push_back(tmp); tmp.ed = v; edge[u].push_back(tmp); } for(i = 1;i <= n;i++) scanf("%d",&gold[i]); t -= dfs_find(1,0); //printf("%dXXX\n",t); if (t <= 0) { printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n"); return 1; } dfs(1,0); printf("%d\n",dp[1][t]); return 1;}int main(){ //freopen("test.in","r",stdin); while(Work()); return 0;}//END
- 分组背包+树形DP(BY LPX)
- HDU 4003 (树形DP + 分组背包)
- POJ 1947 树形DP(分组背包)
- hdu4003 树形dp+分组背包
- hdu4044 树形dp+分组背包
- hdu5148 树形dp,分组背包
- hdu4044GeoDefense 树形dp+分组背包
- hdu4003 树形dp+分组背包
- 树形DP+背包(poj1155泛化分组背包)
- hdu 4003 Find Metal Mineral(树形DP+分组背包)
- 【POJ1947】Rebuilding Roads,树形DP(本文分组背包做法)
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- HDU 4044 GeoDefense(树形DP+分组背包)★
- HDU 4044 GeoDefense(树形DP+分组背包)
- hdu 4003 Find Metal Mineral(树形dp+分组背包)
- hdu 4276 树形DP + 分组背包
- hdu 1561树形dp+分组背包
- hdu 4044 GeoDefense 树形dp+分组背包
- Ubuntu12.10 下搭建基于KVM-QEMU的虚拟机环境(十七)
- [Android开发常见问题-10]PagerTabStrip和PagerTitleStrip异同
- [各种面试题] 链表相关
- 重定向 1>&2 2>&1
- C++中实现回调机制的几种方式
- 分组背包+树形DP(BY LPX)
- 分布式存储系统设计 反熵 (Anti-Entropy)
- DP中的LIS:longest increasing subsequence
- 从今天开始写博客
- 关于C++中数据基础数据类型的一个杂记
- eclipse svn 切换: eclipse svn 切换项目svn地址
- Android开发入门之采用广播接收者实现短信窃听器
- WebStorm 6.0 代码提示配置
- Android中常用动画效果