poj3345 树型DP

来源:互联网 发布:mac吧 编辑:程序博客网 时间:2024/04/27 15:59

这题不难,输入较繁,典型的树形dp

题目大意:一共有n(<=200)个国家, 你想要用收买m(<=m)个国家,其中收买国家i的代价是v[ i ]。但是有些国家有拥属关系,如果A拥属B国,就是买通了A也意味着买通了B,而且这些关系是传递的。求最少需要付出的代价。

在树上背包,代码:

for (k=0;k<g[x].size();k++)
    {
        y=g[x][k];
        for (i=num[x];i>=0;i--)
            for (j=0;j<=i && j<=num[y];j++)
                if (dp[x][i-j]+dp[y][j]<dp[x][i])
                   dp[x][i]=dp[x][i-j]+dp[y][j];
    }

x为根,y是儿子,dp[x][i]表示以x为根的子树取i个的最小代价。(最好先把儿子都遍历完后再dp,这样比较清楚)

挺典型的,可以强化记忆。

这题的输入倒是有点e。。。

我用了sscanf,和sstream来搞。(表示c++是比pascal高级的多啊。。。)

还开了map。(第一次用map,挺方便的,但听说这东西巨慢。。。)

#include <cstdio>#include <cstring>#include <string>#include <vector>#include <map>using namespace std;const int maxn=205,oo=99999999;vector<int> g[maxn];int dp[maxn][maxn],v[maxn],num[maxn];bool fa[maxn];int n,m,id;int dfs(int x){    num[x]=1;    int i,j,k,y;    for (k=0;k<g[x].size();k++)    {        y=g[x][k];        num[x]+=dfs(y);    }    for (k=0;k<=n;k++) dp[x][k]=oo;    dp[x][0]=0;    dp[x][num[x]]=v[x];    for (k=0;k<g[x].size();k++)    {        y=g[x][k];        for (i=num[x];i>=0;i--)            for (j=0;j<=i && j<=num[y];j++)                if (dp[x][i-j]+dp[y][j]<dp[x][i])                   dp[x][i]=dp[x][i-j]+dp[y][j];    }    return num[x];}int main(){    freopen("pin.txt","r",stdin);    freopen("pou.txt","w",stdout);    char str[1000];    int i,j,ans,now;    while (gets(str))    {          if (str[0]=='#') break;          sscanf(str,"%d%d",&n,&m);          map<string,int> wmap;          for (i=0;i<=n;i++)              g[i].clear();          memset(fa,0,sizeof(fa));          id=0;          for (i=1;i<=n;i++)          {              scanf("%s",str);              if (wmap.find(str)==wmap.end())                  wmap[str]=++id;              now=wmap[str];              scanf("%d",&v[now]);              while (getchar()!='\n')              {                    scanf("%s",str);                    if (wmap.find(str)==wmap.end())                       wmap[str]=++id;                    g[now].push_back(wmap[str]);                    fa[wmap[str]]=true;              }          }          v[0]=oo;          for (i=1;i<=n;i++)          {              if (fa[i]) continue;              g[0].push_back(i);          }          dfs(0);          ans=oo;          for (i=m;i<=n;i++)              if (dp[0][i]<ans) ans=dp[0][i];          printf("%d\n",ans);    }    return 0;}


原创粉丝点击