首页 > 代码库 > POJ 1155
POJ 1155
很久以前做的树形DP题,今天再遇到时,竟然不会了,所以写写。。
设数组:
prf[MAX][MAX],cost[MAX],sum[MAX]。分别表示,在第i个结点为根的子树内的情况下,若有j个用户申请看电视,所能得到的最大费用。cost表示传送到i点时所花的费用,而sum表示当前结点为根的子树内已访问的叶子结点的个数(即用户)。
1 void dfs(int v,int fa){ 2 if(T[v].size()>0){ 3 for(int i=0;i<T[v].size();i++){ 4 dfs(T[v][i],v); 5 } 6 } 7 if(T[v].size()==0) 8 sum[v]=1; 9 sum[fa]+=sum[v];10 prf[fa][0]=0;11 for(int i=sum[fa];i>0;i--){12 for(int j=sum[v];j>0;j--){13 if(prf[fa][i-j]!=-INF&&prf[v][j]!=-INF)14 prf[fa][i]=max(prf[fa][i],prf[fa][i-j]+prf[v][j]-cost[v]);15 }16 }17 }
使用深搜,再运用背包来解决。
for(int i=sum[fa];i>0;i--){
for(int j=sum[v];j>0;j--){
if(prf[fa][i-j]!=-INF&&prf[v][j]!=-INF)
prf[fa][i]=max(prf[fa][i],prf[fa][i-j]+prf[v][j]-cost[v])
}
}
枚举父结点当前已访问的用户数,再枚举当前结点子树内该问了的用户数,若要在父结点的状态中加入j个当前结点有用户,则
prf[fa][i]=max(prf[fa][i],prf[fa][i-j]+prf[v][j]-cost[v])。这是拿加入j个用户后与当前i个用户的费用的比较。
前提条件时if(prf[fa][i-j]!=-INF&&prf[v][j]!=-INF),因为要在状态存在的情况下才能进行。
1 #include <iostream> 2 #include <vector> 3 4 const int maxn=3010; 5 const int INF=100000; 6 using namespace std; 7 int n,m; 8 int prf[maxn][maxn]; 9 int cost[maxn];10 int sum[maxn];11 12 vector<int>T[maxn];13 14 void init(){15 for(int i=0;i<=n;i++)16 for(int j=0;j<=m;j++)17 prf[i][j]=-INF;18 memset(cost,0,sizeof(cost));19 memset(sum,0,sizeof(sum));20 for(int i=0;i<=n;i++)21 T[i].clear();22 }23 int max(int a,int b){24 if(a<b)25 return b;26 return a;27 }28 void dfs(int v,int fa){29 if(T[v].size()>0){30 for(int i=0;i<T[v].size();i++){31 dfs(T[v][i],v);32 }33 }34 if(T[v].size()==0)35 sum[v]=1;36 sum[fa]+=sum[v];37 prf[fa][0]=0;38 for(int i=sum[fa];i>0;i--){39 for(int j=sum[v];j>0;j--){40 if(prf[fa][i-j]!=-INF&&prf[v][j]!=-INF)41 prf[fa][i]=max(prf[fa][i],prf[fa][i-j]+prf[v][j]-cost[v]);42 }43 }44 }45 46 int main(){47 while(~scanf("%d%d", &n, &m))48 {49 init();50 int t=0,c,k,y;51 T[0].push_back(1);52 while((++t)<=n-m){53 scanf("%d",&k);54 for(int i=1;i<=k;i++){55 scanf("%d%d",&y,&c);56 T[t].push_back(y);57 cost[y]=c;58 }59 }60 for(k=n-m+1;k<=n;k++){61 scanf("%d",&c);62 prf[k][1]=c;63 prf[k][0]=0;64 }65 dfs(1,0);66 for(int i=m;i>=0;i--)67 if(prf[1][i]>=0){68 printf("%d\n",i);69 break;70 }71 }72 return 0;73 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。