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
- hdu 1561 The more, The Better 树形DP+背包
- hdu 1561 The more, The Better(树形背包)
- hdu 1561 The more, The Better (树形背包dp)
- HDU 1561 The more, The Better 依赖背包+树形DP
- (简单) 树形背包 HDU 1561 The more, The Better
- hdu 1561 The more, The Better 树形dp+背包
- HDU 1561 The more, The Better (树形DP + 01背包)
- hdu 1561 The more, The Better (树形dp+背包)
- hdu 1561 The more, The Better(树形dp+背包)
- HDU 1561 The more, The Better(树形dp+背包)
- HDU 1561 The more, The Better (树形DP+背包)
- hdu 1561 The more, The Better 树形背包
- hdu 1561 The more, The Better(树形dp,树上背包)
- hdu-1561 The more, The Better(树形背包)
- hdu 1561 The more, The Better 树形背包
- HDU 1561 The more, The Better(多重背包+树形DP)
- Hdu-1561 The more, The Better(树形依赖背包)
- HDU 1561 The more, The Better - 依赖背包+树形dp基础
- Java多线程学习(单一线程)
- 自学Python之函数
- Sicily 2683. Alice and Bob
- kali linux 2.0 折腾笔记
- c++ 特性回顾
- hdu 1561 The more, The Better 树形背包
- IOS xmppFramework 加入黑名单
- 20160101自学Linux
- solutions to errors occured when compiling kernel linux-2.6.31.14
- 2016,留下你的心愿,2017,我们一起回来见证!
- ARM指令集详解
- Ubuntu SSH 开启 Root 远程登陆
- OSChina App代码分析之BaseApplication
- Bye,2015;Hi,2016