POJ 1192 最优连通子集【树形DP】
题意: 在一个树中找出权值和最大的一个连通子集。
分析: 和 1463 几乎一样的题, 状态转移方程
// dp[i][0] 以i 为根节点不包含 i 的值
// dp[i][1] 以i 为根节点包含 i 的值
// dp[i][0]=max(dp[j][1],dp[j][0])
// dp[i][1]+=min(dp[j][0],dp[j][1]) j 为 i 的儿子
View Code
#include<stdio.h> #include<string.h> #define clr(x)memset(x,0,sizeof(x)) struct node { int x,y,w; }p[1002]; int abs(int x) { return x>0?x:-x; } bool ok(int i,int j) { if(abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y)==1) return true; return false; } struct tn { int to,next; }e[100000]; int tot; int head[1002]; void add(int s,int u) { e[tot].to=u; e[tot].next=head[s]; head[s]=tot++; } bool v[1002]; int dp[1002][2]; void dfs(int r) { int j,k; dp[r][0]=0; dp[r][1]=p[r].w; v[r]=true; for(j=head[r];j;j=e[j].next) { k=e[j].to; if(!v[k]) { dfs(k); if(dp[k][0]>dp[r][0]) dp[r][0]=dp[k][0]; if(dp[k][1]>dp[r][0]) dp[r][0]=dp[k][1]; if(dp[k][1]>0) dp[r][1]+=dp[k][1]; } } } int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { tot=1; clr(head); clr(v); clr(dp); for(i=0;i<n;i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].w); for(i=0;i<n;i++) for(j=i+1;j<n;j++) if(ok(i,j)) { add(i,j); add(j,i); } dfs(0); printf("%d\n",dp[0][1]>dp[0][0]?dp[0][1]:dp[0][0]); } return 0; }