POJ-3345 Bribing FIPA 树形DP+分组背包

  题目链接:http://poj.org/problem?id=3345

     国家之间可能存在依赖关系,可以求出每个国家向下的每种情况的最优消费,即f[u][i]表示节点为u时选择i个国家的最优消费。自底向上更新时就是分组背包问题了:

    f[u][i]=Min{ f[u][i],f[u][i-j]+f[v][j] | v为u的儿子节点,0<=j<=v子树的节点数 },其实本来是3维的,不过这里用滚动数组优化了。

  1 //STATUS:C++_AC_16MS_588KB
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 #include<math.h>
  6 #include<iostream>
  7 #include<string>
  8 #include<algorithm>
  9 #include<vector>
 10 #include<queue>
 11 #include<stack>
 12 #include<map>
 13 using namespace std;
 14 #define LL __int64
 15 #define pii pair<int,int>
 16 #define Max(a,b) ((a)>(b)?(a):(b))
 17 #define Min(a,b) ((a)<(b)?(a):(b))
 18 #define mem(a,b) memset(a,b,sizeof(a))
 19 #define lson l,mid,rt<<1
 20 #define rson mid+1,r,rt<<1|1
 21 const int N=300,INF=0x3f3f3f3f,MOD=100000000;
 22 const double DNF=100000000000;
 23 
 24 struct Edge{
 25     int u,v;
 26 }e[N];
 27 
 28 int first[N],next[N],vis[N],f[N][N],cost[N],cnt[N];
 29 int n,m,mt;
 30 
 31 void adde(int u,int v)
 32 {
 33     e[mt].u=u,e[mt].v=v;
 34     next[mt]=first[u],first[u]=mt++;
 35 }
 36 
 37 void dfs(int u)
 38 {
 39     int i,j,v,k;
 40     f[u][0]=0;
 41     i=first[u];
 42     if(i==-1){
 43         f[u][1]=cost[u];
 44         cnt[u]=1;
 45         return;
 46     }
 47     for(;i!=-1;i=next[i]){
 48         dfs(e[i].v);
 49         cnt[u]+=cnt[e[i].v];
 50         for(v=cnt[u];v>=0;v--){
 51             for(j=0;j<=v;j++){
 52                 f[u][v]=Min(f[u][v],f[u][v-j]+f[e[i].v][j]);
 53             }
 54         }
 55     }
 56     f[u][++cnt[u]]=cost[u];
 57 }
 58 
 59 int main()
 60 {
 61  //   freopen("in.txt","r",stdin);
 62     int i,j,a,k,kt,ans,id,idfa;
 63     char s[110],cs[N*110];
 64     map<string,int> q;
 65     while(gets(s))
 66     {
 67         if(s[0]=='#')break;
 68         q.clear();
 69         mem(first,-1);
 70         mem(f,INF);
 71         mem(vis,0);mem(cnt,0);
 72         mt=0;
 73         ans=INF;
 74         sscanf(s,"%d%d",&n,&m);
 75         for(i=1,id=0;i<=n;i++){
 76             scanf("%s%d",s,&a);
 77             if(!q[s])q[s]=++id;
 78             idfa=q[s];
 79             cost[idfa]=a;
 80             gets(cs);
 81             if(!cs[0])continue;
 82             for(k=1,j=0;1;k++,j++){
 83                 if(cs[k]==' ' || cs[k]=='\0'){
 84                     s[j]='\0';
 85                     if(!q[s])q[s]=++id;
 86                     kt=q[s];
 87                     vis[kt]=1;
 88                     adde(idfa,kt);
 89                     j=-1;
 90                     if(cs[k]=='\0')break;
 91                 }
 92                 else s[j]=cs[k];
 93             }
 94         }
 95         for(i=1;i<=n;i++){
 96             if(vis[i])continue;
 97             adde(0,i);
 98         }
 99 
100         dfs(0);
101         for(i=m;i<=n;i++)
102             if(f[0][i]<ans)ans=f[0][i];
103 
104         printf("%d\n",ans);
105     }
106     return 0;
107 }

 

posted @ 2013-03-21 14:20  zhsl  阅读(514)  评论(0编辑  收藏  举报