设dp[u][0]为以u为根的子树,子集中没有u的最大权值,dp[u][1]则表示子集中有u。
如果子集中没有u,那么u的所有儿子中只能选一个。
如果子集中有u,那么u的所有儿子要么不选,要么必须在子集中。
状态转移方程
dp[u][0]=max(dp[u][0],max(dp[v][0],dp[v][1]));
dp[u][1]+=max(0,dp[v][1]);
v是u的儿子节点
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define N 1005
using namespace std;
struct POINT
{
int x,y,c;
}p[N];
int dp[N][2];
bool adj(POINT a,POINT b)
{
return abs(a.x-b.x)+abs(a.y-b.y)==1;
}
vector<int>edge[N];
int vis[N],ct;
void dfs(int u)
{
vis[u]=++ct;
int i,len=edge[u].size(),v;
dp[u][0]=0; dp[u][1]=p[u].c;
for(i=0;i<len;i++){
v=edge[u][i];
if(vis[v]) continue;
dfs(v);
dp[u][0]=max(dp[u][0],max(dp[v][0],dp[v][1]));
dp[u][1]+=max(0,dp[v][1]);
}
ct--;
}
int main()
{
int n,i;
scanf("%d",&n);
int j;
for(i=1;i<=n;i++){
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].c);
for(j=1;j<i;j++){
if(adj(p[i],p[j])){
edge[i].push_back(j);
edge[j].push_back(i);
}
}
}
int ans=0;
for(i=1;i<=n;i++){
if(!vis[i]){
dfs(i);
ans=max(ans,max(dp[i][0],dp[i][1]));
}
}
printf("%d\n",ans);
return 0;
}