【树形dp】hdu 2415 Bribing FIPA

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 0x3f3f3f3f
using 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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-05 02:24:29

【树形dp】hdu 2415 Bribing FIPA的相关文章

HDU 2415 Bribing FIPA

Bribing FIPA Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 241564-bit integer IO format: %I64d      Java class name: Main There is going to be a voting at FIPA (Fédération Internationale de Programmation As

fwt优化+树形DP HDU 5909

1 //fwt优化+树形DP HDU 5909 2 //见官方题解 3 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ 4 5 #include <bits/stdc++.h> 6 // #include <iostream> 7 // #include <cstdio> 8 // #include <cstdlib> 9 // #include <algorithm> 10 // #inc

树形dp/hdu 1011 Starship Troopers

题意 有n个房子,1号为起点房子.每个房子里会消耗一定的士兵来获取一定的价值.现在有m个士兵,求问可以获得的最大价值 注意:走过的房子不能再走 注意2:若要消灭这个房子的bugs,必须全部消灭 分析 典型的树形dp,01背包,因为每个房子里要么全杀死bugs,要么一个不动,只有取或不取两种状态 设f[i][j]表示以i为根节点,消耗j个士兵所能获得的最大价值 则f[i][j]=max(f[son[i]][k] + f[i][j-k]); 答案为f[1][m] Accepted Code 1 /*

树形DP [HDU 2196] Computer

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3526    Accepted Submission(s): 1788 Problem Description A school bought the first computer some time ago(so this computer's id is 1). D

树形DP [HDU 1561] The more, The Better

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5506    Accepted Submission(s): 3274 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝

(树形DP) hdu 1561

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5822    Accepted Submission(s): 3469 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物

(树形DP) hdu 1520

Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5619    Accepted Submission(s): 2580 Problem Description There is going to be a party to celebrate the 80-th Anniversary of the

(树形DP) hdu 5148

Cities Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 579    Accepted Submission(s): 179 Problem Description Long long ago,there is a knight called JayYe.He lives in a small country.This countr

(树形DP) hdu 3452

Bonsai Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 783    Accepted Submission(s): 395 Problem Description After being assaulted in the parking lot by Mr. Miyagi following the "All Valley Kar