三道简单树型dp+01背包~~hdu1561,poj1947,zoj3626

以前学树型dp就是随便的看了几道题,没有特别注意树型dp中的小分类的总结,直到上次浙大月赛一道很简单的树型dp都不会,才意识到自己太水了~~come on!

hdu1561:题目给出了很多棵有根树,如果把每棵树的根节点都与0相连,则就是一棵完整的有根树了(N<=200),ACboy从根节点出发,他最多可以攻占m个城市,而每个城市的财富值不一定相同,问ACboy最多可以获得多少财富。就是以每个跟节点做01背包就可以了,dp[i][j]表示以i为根节点已经攻占了j个城市获得的最大财富。不过要注意一下最后要加上根节点的值,因为要求攻占了根节点才能往下攻占,当然节点0除外,具体见代码和注释:

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<vector>
 7 #define see(x) cout<<#x<<":"<<x<<endl;
 8 using namespace std;
 9 const int maxn = 205;
10 int w[maxn], dp[maxn][maxn];
11 vector<int> son[maxn];
12 int n, m;
13 void dfs(int x){
14     int i, j, k;
15     if(son[x].size()==0){
16         dp[x][1] = w[x];
17         return;
18     }
19     for(i=0;i<son[x].size();i++){
20         dfs(son[x][i]);
21     }
22     for(i=0;i<son[x].size();i++){
23         for(j=m;j>=0;j--){
24             for(k=0;k<=j;k++){
25                 if(dp[son[x][i]][k]!=-1&&dp[x][j-k]!=-1){
26                     dp[x][j] = max(dp[x][j],dp[son[x][i]][k]+dp[x][j-k]);
27                 }
28             }
29         }
30     }
31 /*上面就是基本树型DP加背包的基本解法了*/
32     if(x!=0){  //x为0节点时,不需要这种要求
33         for(j=m;j>=0;j--){//处理一下必须攻占根节点才能攻占剩下的子节点的条件,逆序正好可以处理完
34             if(dp[x][j-1]!=-1){
35                 dp[x][j] = dp[x][j-1]+w[x];
36             }
37         }
38     }
39 }
40 void Init(int n){
41     memset(dp,-1,sizeof(dp));
42     for(int i=0;i<=n;i++){
43         dp[i][0] = 0;
44     }
45     for(int i=0;i<=n;i++){
46         son[i].clear();
47     }
48 }
49 int main(){
50     int i, j, k, l;
51     while(~scanf("%d%d",&n,&m)&&(n||m)){
52         Init(n);
53         for(i=1;i<=n;i++){
54             scanf("%d%d",&k,&w[i]);
55             son[k].push_back(i);
56         }
57         w[0] = 0; dfs(0);
58         printf("%d\n",dp[0][m]);
59     }
60 }

poj1947:给出一棵有根树,问孤立出大小为P的子树要断开多少边。就是一个容量为p的背包,树型dp。dp[i][j]表示以i为根孤立出j个节点的树至少需要断开多少条边,于是dp[x][j] = min{dp[x1][j1]+dp[x2][j2]+dp[x3][j3]+……+dp[xn][jn]},j1+j2+j3+……+jn = j,但是也不是完全这样了,其实在对每个背包进行更新时,应该是dp[x][j] = min{dp[x][j],dp[son[x][i]][k]+dp[x][j-k]-2},减2是因为要减去算了两次的x到son[x][i]的那条边,具体见代码,写的挺纠结的。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<vector>
 7 using namespace std;
 8 const int maxn = 155;
 9 vector<int> son[maxn];
10 bool vis[maxn];
11 int dp[maxn][maxn];
12 int n, p;
13 void dfs(int root, int x){
14     int i, j, k;
15     if(x==root) dp[x][1] = son[x].size();
16     else dp[x][1] = son[x].size()+1;
17 
18     for(i=0;i<son[x].size();i++){
19         dfs(root,son[x][i]);
20     }
21     for(i=0;i<son[x].size();i++){
22         for(j=p;j>=0;j--){
23             for(k=0;k<=j;k++){
24                 if(dp[x][k]<maxn&&dp[son[x][i]][j-k]<maxn){
25                     dp[x][j] = min(dp[x][j],dp[x][k]+dp[son[x][i]][j-k]-2);
26                 }
27             }
28         }
29     }
30 }
31 void Init(int n){
32     int i, j;
33     for(i=0;i<=n;i++){
34         for(j=0;j<=n;j++){
35             dp[i][j] = maxn;
36         }
37         son[i].clear();
38         vis[i] = 0;
39     }
40 }
41 int main(){
42     int i, j, k, x1, x2, ans;
43     while(~scanf("%d%d",&n,&p)){
44         Init(n);
45         for(i=0;i<n-1;i++){
46             scanf("%d%d",&x1,&x2);
47             son[x1].push_back(x2);
48             vis[x2] = 1;
49         }
50         for(i=1;i<=n;i++){
51             if(!vis[i]){
52                 dfs(i,i);break;
53             }
54         }
55         ans = maxn;
56         for(i=1;i<=n;i++){
57             ans = min(ans,dp[i][p]);
58         }
59         printf("%d\n",ans);
60     }
61 }

zoj3626:这个就是上次浙大月赛的题了,题意跟hdu1561类似,给出一棵树,n-1条边有不同的边全,n个城市有不同的财富,一个人最多只可以走m/2长度,为最多可以占领多少财富。dp[i][j]表示以i为根继续走了j个长度可以获得的最大财富,自己就是在刷完hdu1561之后简单的改改顺利的a了,两道题可能可以改成一样的写法,不过想到怎么写,就怎么写了

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<vector>
 7 #define see(x) cout<<#x<<":"<<x<<endl;
 8 using namespace std;
 9 const int maxn = 110;
10 vector<int> son[maxn], w[maxn];
11 int val[maxn];
12 int dp[maxn][205];
13 int n, m;
14 void dfs(int x, int pre){
15     int i, j, k;
16     if(son[x].size()==1&&pre==son[x][0]){
17         return;
18     }
19     for(i=0;i<son[x].size();i++){
20         if(pre!=son[x][i]){
21             dfs(son[x][i],x);
22         }
23     }
24     for(i=0;i<son[x].size();i++){
25         if(pre!=son[x][i]){
26             for(j=m-w[x][i];j>=0;j--){
27                 for(k=0;k<=j;k++){
28                     if(dp[son[x][i]][k]!=-1&&dp[x][j-k]!=-1){
29                         dp[x][j+w[x][i]] = max(dp[x][j+w[x][i]],dp[son[x][i]][k]+dp[x][j-k]);
30                     }
31                 }
32             }
33         }
34     }
35 }
36 void Init(int n){
37     memset(dp,-1,sizeof(dp));
38     for(int i=0;i<=n;i++){
39         son[i].clear();
40         w[i].clear();
41     }
42 }
43 int main(){
44     int i, j, k, x1, x2, l, ans;
45     while(~scanf("%d",&n)){
46         Init(n);
47         for(i=1;i<=n;i++){
48             scanf("%d",&val[i]);
49             dp[i][0] = val[i];
50         }
51         for(i=0;i<n-1;i++){
52             scanf("%d%d%d",&x1,&x2,&l);
53             son[x1].push_back(x2);w[x1].push_back(l);
54             son[x2].push_back(x1);w[x2].push_back(l);
55         }
56         scanf("%d%d",&k,&m);
57         m/=2;dfs(k,-1);
58         ans = val[k];
59         for(i=0;i<=m;i++){
60             ans = max(ans,dp[k][i]);
61         }
62         printf("%d\n",ans);
63     }
64 }

 按理说dp都没啥模板,但是其实树上dp+背包,如果不复杂的化,也有点按部就班的感觉了~下次想出状态,寻轨道距应该就能做出来了。

转载于:https://www.cnblogs.com/celia01/archive/2012/08/02/2619063.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css 字体图标更改颜色_在CSS中更改字体

css 字体图标更改颜色CSS字体属性 (CSS font properties ) Font properties in CSS is used to define the font family, boldness, size, and the style of a text. CSS中的字体属性用于定义字体系列 &#xff0c; 粗体 &#xff0c; 大小和文本样式 。 Syntax: 句法&#xf…

深入new/delete:Operator new的全局重载

Operator new 的全局重载 原文地址&#xff1a;http://blog.csdn.net/zhenjing/article/details/4354880 我们经常看到这么一句话&#xff1a; operator new 可以重载&#xff0c; placement new 不可重载。其实此处所说的不可重载应该是指全局的 placement new 不可重载&#…

C++基础知识点整理

基本语法 1、static关键字的作用 1、全局静态变量 加了static关键字的全局变量只能在本文件中使用。 存储在静态存储区&#xff0c;整个程序运行期间都存在。 2、局部静态变量 作用域仍为局部作用域。 不过离开作用域之后&#xff0c;并没有销毁&#xff0c;而是贮存程序中&a…

Haskell学习笔记

《learn you a Haskell》这书的结构与常见的语言入门教材完全不一样。事实上&#xff0c;即使学到第八章&#xff0c;你还是写不出正常的程序…因为到现在为止还没告诉你入口点模块怎么写&#xff0c;IO部分也留在了最后几章才介绍。最重要的是&#xff0c;没有系统的总结数据类…

组合问题 已知组合数_组合和问题

组合问题 已知组合数Description: 描述&#xff1a; This is a standard interview problem to make some combination of the numbers whose sum equals to a given number using backtracking. 这是一个标准的面试问题&#xff0c;它使用回溯功能将总和等于给定数字的数字进…

可变参数模板、右值引用带来的移动语义完美转发、lambda表达式的理解

可变参数模板 可变参数模板对参数进行了高度泛化&#xff0c;可以表示任意数目、任意类型的参数&#xff1a; 语法为&#xff1a;在class或者typename后面带上省略号。 Template<class ... T> void func(T ... args) {// }T:模板参数包&#xff0c;args叫做函数参数包 …

BI-SqlServer

一.概述 SqlServer数据仓库ETL组件 IntegrationServiceOLAP组件 AnalysisService报表 ReportingServiceMDX(查多维数据集用的)和DMX(查挖掘模型用的)。二.商业智能-Analysis Services 项目 构建挖掘模型1构建挖掘模型2构建挖掘模型3三.商业智能-SqlServerAnalysis-Asp.net WebS…

python 子图大小_Python | 图的大小

python 子图大小In some cases, the automatic figure size generated by the matplotlib.pyplot is not visually good or there could be some non-acceptable ratio in the figure. So, rather than allowing a pyplot to decide the figure size, we can manually define t…

《设计模式整理》

目录常见设计模式如何保证单例模式只有一个实例单例模式中的懒汉与饿汉模式OOP设计模式的五项原则单例模式中的懒汉加载&#xff0c;如果并发访问该怎么做常见设计模式 单例模式&#xff1a; 单例模式主要解决了一个全局使用的类频繁的创建和销毁的问题。 单例模式下确保某一个…

JSON学习资料整理

1.什么是JSON JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScript的一个子集。 JSON采用完全独立于语言的文本格式&#xff0c;但是也使用了类似于C语言家族的习惯&#xff08;包括C, C, C#, Java, JavaScript, Perl, Python等&#xff09;。这些…

OSI七层模型及其数据的封装和解封过程

OSI(Open System Interconnection)参考模型把网络分为七层: 1.物理层(Physical Layer) 物理层主要传输原始的比特流,集线器(Hub)是本层的典型设备; 2.数据链路层(Data Link Layer) 数据链路层负责在两个相邻节点间无差错的传送以帧为单位的数据,本层的典型设备是交换机(Switch)…

rss聚合模式案例_RSS的完整形式是什么?

rss聚合模式案例RSS&#xff1a;真正简单的联合 (RSS: Really Simple Syndication) RSS is an abbreviation of Really Simple Syndication. It is also called Rich Site Summary. It is quality attainment for the syndication of collection of web content and used to di…

《MySQL——38道查询练习(无连接查询)》

目录一、准备数据1、创建数据库2、创建学生表3、创建教师表4、创建课程表5、创建成绩表6、添加数据二、查询练习1、查询 student 表的所有行2、查询 student 表中的 name、sex 和 class 字段的所有行3、查询 teacher 表中不重复的 department 列4、查询 score 表中成绩在60-80之…

工作经常使用的SQL整理,实战篇(一)

工作经常使用的SQL整理&#xff0c;实战篇&#xff08;一&#xff09; 原文:工作经常使用的SQL整理&#xff0c;实战篇&#xff08;一&#xff09;工作经常使用的SQL整理&#xff0c;实战篇&#xff0c;地址一览&#xff1a; 工作经常使用的SQL整理&#xff0c;实战篇&#xff…

XPth和XSLT的一些简单用法

&#xff08;目的在于让大家知道有这个东西的存在&#xff09; XPath:即XML Path语言(Xpath)表达式使用路径表示法(像在URL中使用一样)来为XML文档的各部分寻址&#xff01; 关于XPath如何使用了&#xff0c;我们来看看&#xff01;当然这里面的代码只是入门&#xff0c;更深层…

isc dhcp_ISC的完整形式是什么?

isc dhcpISC&#xff1a;印度学校证书 (ISC: Indian School Certificate) ISC is an abbreviation of the Indian School Certificate. It alludes to the 12th class examination or higher secondary examination conducted by the Council for the Indian School Certificat…

《MySQL——连接查询》

内连接&#xff1a; inner join 或者 join 外连接 1、左连接 left join 或 left outer join 2、右连接 right join 或 right outer join 3、完全外连接 full join 或 full outer join 图示理解 全连接 创建person表和card表 CREATE DATABASE testJoin;CREATE TABLE person (…

win7下 apache2.2 +php5.4 环境搭建

这篇文章很好 没法复制 把链接粘贴来http://www.360doc.com/content/13/0506/13/11495619_283349585.shtml# 现在能复制了&#xff1a; 把任何一篇你要复制、却不让复制的文章收藏入收藏夹(直接CtrlD,确定) 2在收藏夹中&#xff0c;右击刚才收藏的那个网址&#xff0c;点属性 3…

HDU_1533 Going Home(最优匹配) 解题报告

转载请注明出自cxb:http://blog.csdn.net/cxb569262726 题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1533 说实话&#xff0c;这个题目刚开始还真看不出是完备匹配下的最大权匹配&#xff08;当然&#xff0c;这个也可以用网络流做。&#xff08;应该是添加…

c#中 uint_C#中的uint关键字

c#中 uintC&#xff03;uint关键字 (C# uint keyword) In C#, uint is a keyword which is used to declare a variable that can store an integral type of value (unsigned integer) the range of 0 to 4,294,967,295. uint keyword is an alias of System.UInt32. 在C&…