poj 1155

树形dp 结合01背包

View Code
 1 #include<cstdio>
2 #include<cstring>
3 #define max(a,b) a>b?a:b
4 const int INF = 1000000000;
5 const int maxn = 3010;
6 int head[maxn],dp[maxn][maxn],n,m;
7 int num[maxn];
8 struct EDGE{
9 int v,w,next;
10 }edge[maxn];
11 int tot;
12 void add_edge(int s,int t,int w){
13 edge[tot].v=t;
14 edge[tot].w=w;
15 edge[tot].next=head[s];
16 head[s]=tot++;
17 }
18 void dfs(int u){
19 int i,j,k,tmp[maxn];
20 for(i=head[u];i!=-1;i=edge[i].next){
21 int v=edge[i].v;
22 dfs(v);
23 for(j=0;j<=num[u];j++)
24 tmp[j]=dp[u][j];
25 for(j = 0; j <= num[u]; j ++)
26 for(k = 1; k <= num[v]; k ++)
27 dp[u][j+k] = max(dp[u][j+k], tmp[j]+dp[v][k]-edge[i].w);
28 num[u] += num[v];//利用回溯,自底向上的进行DP
29 }
30 }
31 int main(){
32 int i,j,k,a,c;
33 tot=0;
34 memset(head,-1,sizeof(head));
35 scanf("%d%d",&n,&m);
36 for(i=1;i<=n;i++)
37 for(j=1;j<=n;j++)
38 dp[i][j]=-INF;
39 for(i=1;i<=n-m;i++){
40 scanf("%d",&k);
41 for(j=0;j<k;j++){
42 scanf("%d%d",&a,&c);
43 add_edge(i,a,c);
44 }
45 }
46 memset(num,0,sizeof(num));
47 for(i=n-m+1;i<=n;i++){
48 num[i]=1;
49 scanf("%d",&dp[i][1]);
50 }
51 dfs(1);
52 for(i=m;i>=0;i--){
53 if(dp[1][i]>=0){
54 printf("%d\n",i);
55 break;
56 }
57 }
58 return 0;
59 }



posted @ 2012-03-17 12:10  静静的等待_93  阅读(291)  评论(0编辑  收藏  举报