您的位置:首页 > 其它

树形DP-Bribing FIPA

2017-11-18 22:42 357 查看


Bribing FIPA

 (树形DP)

题意:给定n,m,接下来n行每行给一个城市,给出到城市的费用和与通向它的城市(可能没有)。

问你至少访问m个城市的情况下,使费用最小。

思路:

就是一个树形DP节点的分配问题,状态转移方程为 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[z][k]);//分配k个要访问的节点给z子节点

注意初始化,具体见代码。

最坑的是输入。用一个map把字符串映射为数,用gets读入判断‘#’,sscanf 取出s中的整数m和n,ch=getchar()判断输入费用之后知否还有别的城市。构造0为根。输入是从网上看的,长见识了。这道题还是有难度的,不过我觉得主要难在初始化和输入上。

#include<iostream>

#include<cmath>

#include<cstring>

#include<algorithm>

#include<cstdio>

#include<string>

#include<queue>

#include<vector>

#include<map>

using namespace std;

const int mx=205;

const int inf=0x3f3f3f3f;

struct node{

 int w,v,nex;

}a[mx<<1];

int t,dp[mx][mx],fa[mx],c[mx],h[mx],sum[mx],n,m;

map<string,int> mp;//city映射为数来建树

void add(int z,int f)

{

    a[t].v=z;

    a[t].nex=h[f];

    h[f]=t++;

}

void dfs1(int u)

{

 sum[u]=1;//统计这一个节点的数目 

 dp[u][0]=0;//访问0个点费用为0

 int j,k;

 for(int i=h[u];i!=-1;i=a[i].nex)

 {

  int z=a[i].v;

  dfs1(z);

  sum[u]+=sum[z];

  for(j=sum[u];j>=1;j--){

  for(k=0;k<=j&&k<=sum[z];k++) dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[z][k]);//访问子树的k个点

 }

 }

 dp[u][sum[u]]=c[u];//这是关键。遍历完整颗子树,则值为c[u]

}

int main()

{

    int T,ans,num;

    char s[mx],sz[mx],sf[mx],ch;

    while(gets(s)&&s[0]!='#')//gets 读入带空格的字符串

    {

     sscanf(s,"%d%d",&n,&m);//sscanf从s中取出整数n和m,新学的,记住

     memset(h,-1,sizeof(h));

     memset(fa,-1,sizeof(fa));

     memset(dp,0x3f,sizeof(dp));

     memset(sum,0,sizeof(sum));

     mp.clear();num=0;t=0;//注意初始化

     int w;

     for(int i=1;i<=n;i++)

     {

      scanf("%s%d",s,&w);

      if(mp.count(s)==0) mp[s]=++num;//建立映射

      c[mp[s]]=w;

      while(1)

      {

          ch=getchar();

          if(ch=='\n') break;//输入回车说明该组输入已经结束

          scanf("%s",sz);

          if(mp.count(sz)==0) mp[sz]=++num;

          add(mp[sz],mp[s]);

          fa[mp[sz]]=mp[s];//记录父节点,最后没有父节点的都连到0,0即为树的根

      }

     }

     for(int i=1;i<=n;i++) if(fa[i]==-1) add(i,0);//连接根

     sum[0]=n;

     dfs1(0);

     ans=inf;

     for(int i=m;i<=n;i++) ans=min(ans,dp[0][i]);//最小值即为能访问至少m个城市的最小费用

     printf("%d\n",ans);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树形dp dp