题意:就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值。
一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m)时选最多的宝物,而一个子节点中只可以选择一个状态进行转移,每个节点有若干个子节点,问题就转换为分组背包,几个子节点就是几个分组背包,体积是选几个地点,价值是宝物价值。
状态转移方程: dp[v][1] = Money[v]; (v为叶子节点)
dp[v][j] = max(dp[v][j],dp[v][j-i] + dp[k][i] );(v为非叶子节点,j表示用户个数,i为容量,k为v的子节点,)
是不是分组背包都无所谓,直接按照方程来了,可能j的值是需要逆向枚举用到背包吧
2015-05-11:
和bug那题一模一样,我会乱说?链接:点我
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("*****\n"); 15 const int MAXN=1005; 16 int dp[MAXN][MAXN],val[MAXN],head[MAXN]; 17 int n,m,tt,tot; 18 struct Edge 19 { 20 int to,next; 21 }edge[MAXN]; 22 void addedge(int u,int v) 23 { 24 edge[tot].to=v; 25 edge[tot].next=head[u]; 26 head[u]=tot++; 27 } 28 void init() 29 { 30 memset(head,-1,sizeof(head)); 31 tot=0; 32 memset(dp,0,sizeof(dp)); 33 } 34 void dfs(int u,int pre) 35 { 36 dp[u][1]=val[u]; 37 for(int i=head[u];i!=-1;i=edge[i].next) 38 { 39 int v=edge[i].to; 40 if(v==pre) continue; 41 dfs(v,u); 42 for(int j=m;j>=1;j--) 43 { 44 for(int k=1;j-k>=1;k++) 45 { 46 dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]); 47 } 48 } 49 } 50 } 51 int main() 52 { 53 int i,j,k; 54 #ifndef ONLINE_JUDGE 55 freopen("1.in","r",stdin); 56 #endif 57 while(scanf("%d%d",&n,&m)!=EOF) 58 { 59 if(n==0&&m==0) break; 60 init(); 61 for(i=1;i<=n;i++) 62 { 63 int a; 64 scanf("%d%d",&a,&val[i]); 65 addedge(a,i); 66 } 67 m++; //多了一个0节点 68 val[0]=0; 69 dfs(0,-1); 70 printf("%d\n",dp[0][m]); 71 } 72 }
时间: 2024-10-15 00:52:28