1. 程式人生 > >POJ 1192 最優連通子集(樹形DP)

POJ 1192 最優連通子集(樹形DP)

最優連通子集

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 3100 Accepted: 1666

Description

眾所周知,我們可以通過直角座標系把平面上的任何一個點P用一個有序數對(x, y)來唯一表示,如果x, y都是整數,我們就把點P稱為整點,否則點P稱為非整點。我們把平面上所有整點構成的集合記為W。 
定義1 兩個整點P1(x1, y1), P2(x2, y2),若|x1-x2| + |y1-y2| = 1,則稱P1, P2相鄰,記作P1~P2,否則稱P1, P2不相鄰。 
定義 2 設點集S是W的一個有限子集,即S = {P1, P2,..., Pn}(n >= 1),其中Pi(1 <= i <= n)屬於W,我們把S稱為整點集。 
定義 3 設S是一個整點集,若點R, T屬於S,且存在一個有限的點序列Q1, Q2, ?, Qk滿足: 
1. Qi屬於S(1 <= i <= k); 
2. Q1 = R, Qk = T; 
3. Qi~Qi + 1(1 <= i <= k-1),即Qi與Qi + 1相鄰; 
4. 對於任何1 <= i < j <= k有Qi ≠ Qj; 
我們則稱點R與點T在整點集S上連通,把點序列Q1, Q2,..., Qk稱為整點集S中連線點R與點T的一條道路。 
定義4 若整點集V滿足:對於V中的任何兩個整點,V中有且僅有一條連線這兩點的道路,則V稱為單整點集。 
定義5 對於平面上的每一個整點,我們可以賦予它一個整數,作為該點的權,於是我們把一個整點集中所有點的權的總和稱為該整點集的權和。 
我們希望對於給定的一個單整點集V,求出一個V的最優連通子集B,滿足: 
1. B是V的子集 
2. 對於B中的任何兩個整點,在B中連通; 
3. B是滿足條件(1)和(2)的所有整點集中權和最大的。 

Input

第1行是一個整數N(2 <= N <= 1000),表示單整點集V中點的個數; 
以下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

Noi 99

【思路】

整體的思路輪廓就兩句話:

1、這是一棵樹,最優連通塊必定也呈現樹狀的結構。

2、在以某個節點為根的子樹中,分包含此點與不包含此點兩種情況傳遞必能得到最優結果。

【程式碼】

//******************************************************************************
// File Name: POJ_1192.cpp
// Author: Shili_Xu
// E-Mail: [email protected]
// Created Time: 2018年08月07日 星期二 17時06分43秒
//******************************************************************************

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;

const int MAXN = 1005;

struct node {
	int x, y, c;
};

int n;
node p[MAXN];
vector<int> g[MAXN];
int dp[MAXN][2];

void dfs(int u, int fa)
{
	dp[u][0] = 0;
	dp[u][1] = p[u].c;
	for (int i = 0; i < g[u].size(); i++) {
		int v = g[u][i];
		if (v == fa) continue;
		dfs(v, u);
		dp[u][0] = max(dp[u][0], max(dp[v][0], dp[v][1]));
		dp[u][1] += (dp[v][1] > 0 ? dp[v][1] : 0);
	}
}

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].c);
	for (int i = 1; i <= n - 1; i++)
		for (int j = i + 1; j <= n; j++) {
			if (abs(p[i].x - p[j].x) + abs(p[i].y - p[j].y) == 1)
				g[i].push_back(j), g[j].push_back(i);
		}
	dfs(1, 0);
	printf("%d\n", max(dp[1][0], dp[1][1]));
	return 0;
}

相關推薦

POJ 1192 連通子集樹形DP

最優連通子集 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3100 Accepted: 1666 Description 眾所周知,我們可以通過直角座標系把平面

poj 1192 連通子集 樹狀dp

最優連通子集 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2431 Accepted: 1294 Description 眾所周知,我們可以通過直角座標系把平面上的任何一個點P用一個有序數對

POJ-1192-連通子集

本來書上是放在最短路徑那章的,寫了半天發現很麻煩,一搜索才知道這個題應該用樹形DP做, 算是比較簡單的樹形DP題吧。 程式碼: #include<cstdio> #include<cstring> #include<iostream> #

POJ1192連通子集(樹狀dp)

最優連通子集 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2140 Accepted: 1139 Description 眾所周知,我們可以通過直角座標系把平面上的任何一個點P用一個有序數對(

2018.10.25【NOIP練習】大瘋子樹樹形DP

傳送門 解析: 其實簡單推一下我們發現一個瘋子樹內部任何一條路徑上點權都是單峰下凸的。 證明也很簡單,不過請記住一點,考場上沒有必要去想證明,除非你時間真的很充裕。 必要性:如果不是單峰下凸,則不是瘋子樹。 考察如果尋在一條不是單峰下凸的路徑,那麼這個路徑的某

連通子集的解法

關於POJ1192,求最優連通子集。 下面是POJ的題目描述: Description 眾所周知,我們可以通過直角座標系把平面上的任何一個點P用一個有序數對(x, y)來唯一表示,如果x, y都是整數,我們就把點P稱為整點,否則點P稱為非整點。我們把平面上所有整點構成的

POJ題目1947 Rebuilding Roads樹形dp

line div space cpp i++ tex tab wan blue Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9957 Acc

POJ】1935 Journey樹形dp

scan AR urn vector 答案 span ace CA include 題目 傳送門:QWQ 分析 涼涼。 答案是所有要經過的點到根所經過的邊權和減去最大的邊權。 代碼 vector好慢啊 #include <

POJ - 2342】Anniversary party樹形dp

There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure of employe

Party at Hali-Bula POJ - 3342樹形dp

Dear Contestant, I’m going to have a party at my villa at Hali-Bula to celebrate my retirement from BCM. I wish I could invite all my co-workers

POJ - 3342 Party at Hali-Bula 樹形DP+STL

POJ - 3342 Party at Hali-Bula (樹形DP+STL) Dear Contestant, I’m going to have a party at my villa at Hali-Bula to celebrate my retirement from B

1463】Strategic game 樹上小點覆蓋,樹形dp

題幹: Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is v

POJ - 1947 - Rebuilding Roads樹形dp

The cows have reconstructed Farmer John’s farm, with its N barns (1 <= N <= 150, number 1…N) after the terrible earthquake last May. The cow

分解問題Java版

import java.util.*; public class NiceDec { public static void main(String[] args) { Scanner in

裝載問題貪心基礎

最優裝載問題。給出n個物體,第i個物體重量為w[i]。選擇儘量多的物體,使得總重量不超過C。 【分析】 由於只關心物體的數量,所有裝重的沒有裝輕的划算。只需把所有物體按重量從小到大排序,一次

POJ-1655 樹的重心樹形 DP

題目 題意 定義一個點的“平衡”值等於將這個點拆去後,形成的子樹中節點數的最大值。求一棵樹“平衡”值最小的點。 題解 這其實就是樹的重心的概念,通過樹形 dp 很容易解決。當去掉抹一點後,它下面的子樹的節點個數通過 dfs 可以得到,它上面的

裝載問題貪心法

問題描述: 有一批集裝箱要裝上一艘載重量為c的輪船。其中集裝箱i的重量為Wi。最優裝載問題要求確定在裝載體積不受限制的情況下,將盡可能多的集裝箱裝上輪船。 問題可以描述為: 式中,變數xi = 0 表示不裝入集裝箱 i,xxi = 1 表示裝入集裝箱 i。

CCF201409-4 配餐100分

試題編號: 201409-4 試題名稱: 最優配餐 時間限制: 1.0s 記憶體限制: 256.0MB 問題描述: 問題描述   棟棟最近開了一家餐飲連鎖店,提供外賣服務。隨著連鎖店越來越多,怎麼合理的給客戶送餐成為了一個急需解決的問題。   棟棟的

HDU 4717樹形DP

== cnblogs div code 刪除 splay 沒有 str std 由於內存的限制。所以盡量要少開數組。一開始用了數組記錄每個點的度數和每個點的兒子數,還有vis記錄這個點是否處理過。然後超內存了。 實際上兒子數沒有必要存下來,只是每次遍歷自身的時候會用到,然後

Perfect Service UVA - 1218樹形dp

pen perf name isp 技術 get sca code esp Perfect Service UVA - 1218 題意:安裝服務器,使得不是服務器的計算機恰好和一臺服務器計算機相連。問最少安多少服務器計算機。 之前一直不理解第三個轉移方程,,今天再看竟然是