【树形dp】hdu 2415 Bribing FIPA
来源:互联网 发布:百度云计算阳泉中心 编辑:程序博客网 时间:2024/05/16 08:21
hdu 2415 Bribing FIPA
题目:给定由若干个树组成的森林, 树上的边是有向边, 树上的每个节点都有一个代价. 若要得到某个节点, 需要付出该节点对应的代价, 若该节点拥有后继, 那么后继的节点也都能获得. 求解使用最少的代价取得至少 m 个节点
这道题输入是个问题,之前用 getchar()!='\n' 调了一晚上始终过不了,最后用C++的stringstream过了,还以为是dfs的问题,输入是巨坑!!!
说一下思路(1)建树的时候会遇到孤立结点,设想一个虚拟节点0,没有前驱的节点都作为虚拟根节点的后继,从而建立一个森林,这一步比较容易想到;
(2)dp[i][j]表示第i个国家及其附属国中选j个国家的最小花费;
状态转移方程为:dp[u][j+k] = min(dp[u][j], dp[u][j-k]+dp[v][k]) 需要理解!
(3)dp[u][j]的初始化问题:对于子树u使得 j~1:tot[u] 的所有dp[u][j]=v[u] ,其中tot[u]代表子树u的所有节点个数,v[u]表示节点u的费用;由于无法事先确定tot[u],只能边搜索边返回,然后取min:dp[u][j]=min{dp[u][j],v[u]},最后使用带返回值的dfs(int u)__返回子树u的所有节点数目
最后,vector<>建树,map<>给国家编号,树形dp求解
sscanf的使用
使用stringstream对象简化类型转换
详细理解见注释:
/*Author:Hacker_vision*/#include<bits/stdc++.h>#define clr(k,v) memset(k,v,sizeof(k))#define INF 0x3f3f3f3fusing namespace std;const int _max=3e2+10;int n,m,v[_max];//有n个国家及其附属关系,要从中选择m个国家得到m张投票;v[i]表示i的花费char str1[110],str2[110];int dp[310][310];//dp[u][j]=min(dp[u][j],dp[u->child][j-k]+dp[u->child][k])bool vis[310];//判断是否有孤立结点,是的话加到虚节点vector<int>child[_max];//vector建树map<string,int>mp;//mp映射,给国家名编号map<int,string>name;int dfs(int u){ int size=child[u].size(); int tot=1; //存储子树i包含的所有结点数目,包括树根 dp[u][0]=0; dp[u][1]=v[u]; for(int i = 0; i < size; ++ i ){ tot+=dfs(child[u][i]); //递归返回部分,记录子树u包含的节点数,用作初始化 for(int j = n;j >= 0; -- j ){ for( int k = 0; k <= j; ++ k){ dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[child[u][i]][k]);//子节点选j-k,其他的选k个,完成选择 } //尝试理解所有节点遍历完的情况一定是最优解 } //注意:不一定选m个国家正合适,可能超过m反而更小,从n计数 } for(int i=1; i<= tot;i++) dp[u][i]=min(dp[u][i],v[u]); //这部分本来应该作初始化的,但是不知道子树u的结点数, return tot; //只能边递归边初始化:若放在之前的话dp[u][i]=v[u];}int main(){ // freopen("input.txt","r",stdin); char str[1000]; while( gets(str) && str[0] != '#') { sscanf(str,"%d%d", &n, &m); int top=1,cost; clr(vis,0); for(int i=0; i<=n; ++i ) child[i].clear(); mp.clear();//使用vector\map容器先清空 for(int i=1; i<=n; ++i ){ scanf("%s%d",str1,&cost); if(!mp[str1]) mp[str1]=top++; v[mp[str1]]=cost;//cost赋值给对应编号的费用v[]中 name[i]=str1; gets(str); stringstream ss(str); //ss读入str while( ss >> str2 ) { //ss读出到str2 if(!mp[str2]) mp[str2]=top++; child[mp[str1]].push_back(mp[str2]); vis[mp[str2]]=true; } } v[0]=INF; for( int i =1;i <=n; i++ ) if(vis[i]==false) child[0].push_back(i);//孤立节点i加入虚拟根节点,构建森林 for( int i =0;i <=n; i++ ) for( int j = 0; j<= n ; ++ j ) dp[i][j]=INF; //因为要取最小值,dp[][]初始化最大即可 dfs(0);//从虚拟节点深搜 printf("%d\n",*min_element(dp[0]+m,dp[0]+n+1));//找到选择m~n个国家中的最小值 } return 0;}
1 0
- 【树形dp】hdu 2415 Bribing FIPA
- POJ 3345 HDU 2415 Bribing FIPA(树形DP)
- 树形DP-Bribing FIPA
- HDU 2415 Bribing FIPA(树形背包)
- POJ3345 Bribing FIPA 树形DP
- Bribing FIPA(树形DP)
- Bribing FIPA (树形dp)
- hdu 2415 Bribing FIPA
- POJ 3345 Bribing FIPA 树形DP
- 【树形dp】PKU-3345-Bribing FIPA
- POJ 3345 Bribing FIPA 树形dp
- poj 3345 Bribing FIPA 树形dp
- poj 3345 Bribing FIPA[树形dp+背包]
- 【树形DP】 POJ 3345 Bribing FIPA
- POJ 3345 Bribing FIPA / 树形DP
- POJ 3345 Bribing FIPA 树形dp
- poj 3345 Bribing FIPA(树形dp)
- POJ3345---Bribing FIPA(树形dp+背包)
- Hbase:namespace异常处理,hbase异常处理
- SpringMVC快速实现文件上传功能
- 导出数据库数据生成xml
- android学习笔记之Activity生命周期详解
- 重定向和其他请求变化
- 【树形dp】hdu 2415 Bribing FIPA
- 快速了解Scala技术栈
- Web Navigation(1028)
- MSSQL 的OVER()函数
- PlistBuddy用法举例
- iOS培训日志连载一
- Nginx启动停止脚本
- 安装VMware Tool
- 一文教你看懂大数据的技术生态圈:Hadoop,hive,spark