Description
Bob喜欢玩跳格子的游戏。这天,他在地上画了一些格子,每个格子有个坐标(x,y),Bob每次只能从一个格子跳到相邻的距离为1的格子。
Bob发现,从任意一个格子跳到另一个格子的路径有且仅有一条。现在Bob给每个格子一个分数,他想选一些格子,这些格子两两可达,并且权值和最大,你能帮他实现吗。
Input
第1行是一个整数N(2 <= N <= 1000),表示格子个数;
以下N行中,第i行(1 <= i <= N)有三个整数,Xi, Yi, Ci依次表示第i个格子的横坐标,纵坐标和权。同一行相邻两数之间用一个空格分隔。-10^6 <= Xi, Yi <= 10^6;-100 <= Ci <= 100。
Output
仅一个整数,表示所选格子的权值和。
Sample Input
5
0 0 -2
0 1 1
1 0 1
0 -1 1
-1 0 1
Sample Output
2
Source
/*算法思想: 给一棵树,要求在树上选择几个相互联通的点,使得他们的权值和最大 每个节点有两种状态: 1、f[i][0]:节点 i 不选; 2、f[i][1]:节点 i 要选; 那么,可以这样定义状态: A、f[i][0]:节点 i 不选,以节点 i 为根的子树所能组成的最大权值和 B、f[i][1]:节点 i 要选,以节点 i 为根的子树所能组成的最大权值和 于是,就有了一下的状态转移方程: 1)、f[i][0]=max(f[i_son][0] , f[i_son][1]); 因为节点 i 不选的话,我们只能选择他的一棵子树,而这颗子树有两种状态:根节点选与不选 2)、if f[i_son][1]>0 then f[i][1]+=f[i_son][1]; 因为节点 i 要选的话,我们必须选择所有权值和大于0的子树,保证所选择点的连通性 最后,这道题需要小心的是,最少选择一个,就是因为这里,WA了好久! */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define INF 0x7fffffff using namespace std; struct node { int x,y,val; } a[1005]; struct data { int st,en,next; } edge[20005]; int f[20005][2],d[20005]; int head[20005],tot; void add_edge(int st,int en) //添加边 { edge[tot].st=st; edge[tot].en=en; edge[tot].next=head[st]; head[st]=tot++; } void dfs(int v,int fa) //树形dp过程(实际上就是dfs) { if(d[v]==1 && v!=1) { f[v][0]=0; f[v][1]=a[v].val; return; } for(int i=head[v];i!=-1;i=edge[i].next) { if(edge[i].en==fa) continue; dfs(edge[i].en,v); f[v][0]=max(f[v][0],max(f[edge[i].en][0],f[edge[i].en][1])); if(f[edge[i].en][1]>0) f[v][1]+=f[edge[i].en][1]; } f[v][1]+=a[v].val; } int main() { int n; while(scanf("%d",&n)!=EOF) { int ans=-INF; for(int i=1;i<=n;i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val); ans=max(ans,a[i].val); } if(ans<=0) printf("%d\n",ans); else { memset(head,-1,sizeof(head)); tot=0; memset(d,0,sizeof(d)); for(int i=1;i<=n;i++) //建树 for(int j=i+1;j<=n;j++) if((fabs(a[i].x-a[j].x)==1 && a[i].y==a[j].y) || (fabs(a[i].y-a[j].y)==1 && a[i].x==a[j].x)) { add_edge(i,j); add_edge(j,i); d[i]++; d[j]++; } memset(f,0,sizeof(f)); dfs(1,0); //随便找一个点作为根节点就行了,这里是以的 1 为根节点 if(n!=1) printf("%d\n",max(f[1][1],f[1][0])); else printf("%d\n",a[1].val); } } return 0; }