hdu 1561 The more, The Better 树形背包

来源:互联网 发布:asp客服源码 编辑:程序博客网 时间:2024/05/17 04:22

The more, The Better

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6661    Accepted Submission(s): 3923


Problem Description
ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗?
 

Input
每个测试实例首先包括2个整数,N,M.(1 <= M <= N <= 200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。
 

Output
对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。
 

Sample Input
3 20 10 20 37 42 20 10 42 17 17 62 20 0
 

Sample Output
513
 

Author
8600
 

Source
HDU 2006-12 Programming Contest
 

Recommend
LL   |   We have carefully selected several similar problems for you:  2159 1203 2602 3033 2415 



#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<climits>#include<queue>#include<vector>#include<map>#include<sstream>#include<set>#include<stack>#include<cctype>#include<utility>#pragma comment(linker, "/STACK:102400000,102400000")#define PI (4.0*atan(1.0))#define eps 1e-10#define sqr(x) ((x)*(x))#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)#define  lson   ind<<1,le,mid#define rson    ind<<1|1,mid+1,ri#define MID   int mid=(le+ri)>>1#define zero(x)((x>0? x:-x)<1e-15)#define mk    make_pair#define _f     first#define _s     second#define ysk(x)  (1<<(x))using namespace std;//const int INF=    ;typedef long long ll;//const ll inf =1000000000000000;//1e15;//ifstream fin("input.txt");//ofstream fout("output.txt");//fin.close();//fout.close();//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);const int INF =0x3f3f3f3f;const int maxn=200+10    ;const int maxV=200+10    ;int n,V;int val[maxn];bool root[maxn];int dp[maxn][maxV];int ans[maxV];vector<int >  ve;vector<int >  G[maxn];void init(){    for(int i=1;i<=n;i++) G[i].clear();    memset(root,0,sizeof root);}void dfs(int x){    dp[x][0]=0;    for(int v=1;v<=V;v++)    {        dp[x][v]=val[x];    }    for(int i=0;i<G[x].size();i++)    {         int y=G[x][i];         dfs(y);         for(int v=V;v>=1;v--)         {             for(int v2=0;v2<v;v2++)             {                 dp[x][v]=max(dp[x][v],dp[x][v-v2]+dp[y][v2]);             }         }    }}int main(){    int x,y;    while(~scanf("%d%d",&n,&V)&&(n||V))    {        init();        for(int i=1;i<=n;i++)        {            scanf("%d%d",&x,&val[i]);            if(x)  G[x].push_back(i);            else  root[i]=1;        }       ve.clear();        for(int i=1;i<=n;i++) if(root[i])        {             dfs(i);             ve.push_back(i);        }        memset(ans,0,sizeof ans);        for(int i=0;i<ve.size();i++)        {             for(int v=V;v>=0;v--)             {                int x=ve[i];                for(int v2=0;v2<=v;v2++)                {                    ans[v]=max(ans[v],ans[v-v2]+dp[x][v2]);                }             }        }        printf("%d\n",ans[V]);    }    return 0;}


http://blog.csdn.net/woshi250hua/article/details/7637847

看看这篇博客的写法,

非常巧妙的添加边。

添加一个虚拟结点0,

然后连边到所有树的树根。

最后0成了树根。

然后dfs遍历树,对于0和其它节点的状态转移区别对待。

因为0结点是不用选择的。

在我的代码中因为对于非0结点首先是必选的。

所以我最先把v>=1的地方dp[x][v]都赋值为val[x];

而这份代码中是最后赋值的,其实这是都行的。

这份代码的考虑方式是,先考虑子结点的状态转移,在考虑自身。

 if (v != 0) {            for (j = m; j >= 1; --j)              dp[v][j] = dp[v][j-1] + money[v];   //必选当前节点自己      } 

然而这样的转移就不能用max了,因为添加自己是必须的。



16-7-28:

#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<vector>using namespace std;#define all(x) (x).begin(), (x).end()#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)typedef long long ll;typedef pair<int, int> pii;const int INF =0x3f3f3f3f;const int maxn=200    ;int n,m;vector<int >G[maxn+3];int a[maxn+3];bool vis[maxn+3];int num[maxn+3], dp[maxn+3][maxn+3];int ans[maxn+3];void dfs(int x){    num[x]=1;    dp[x][1]=a[x];    for(int i=0;i<G[x].size();i++)    {        int y=G[x][i];        dfs(y);        num[x]+=num[y];        for(int v=num[x];v>=1;v--)        {            for(int v2=0;v2<v;v2++)            {                dp[x][v]=max(dp[x][v],dp[x][v-v2]+dp[y][v2]);            }        }    }}int main(){   std::ios::sync_with_stdio(false);   while(cin>>n>>m&&(n||m))   {         int x,y;        for1(i,n)       {           G[i].clear();       }       memset(vis,0,sizeof vis);       memset(dp,0,sizeof dp);       for1(i,n)       {           cin>>x>>y;           a[i]=y;           if(x) {G[x].push_back(i); vis[i]=1;}       }       memset(ans,0,sizeof ans);       for1(i,n)if(!vis[i])       {          dfs(i);          for(int v=m ;v>=0 ;v--)          {             for(int v2=0;v2<=v;v2++)             {                 ans[v]=max(ans[v],ans[v-v2]+ dp[i][v2] );             }          }       }       cout<<ans[m]<<endl;   }   return 0;}


0 0