UESTC 1686——跳格子

跳格子

Time Limit: 1000 ms Memory Limit: 65535 kB Solved: 34 Tried: 102

Submit

Status

Best Solution

Discuss

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;
}


 

你可能感兴趣的:(UESTC 1686——跳格子)