藍橋杯---Castles---樹形DP(含 BUG)

試題 算法訓練 Castles

資源限制

  時間限制:1.0s 內存限制:256.0MB

問題描述

  戰爭在世界歷史中扮演了重要角色。與現代戰爭不同,中世紀的軍隊主要忙於奪取和控制貴族的私有設防住宅——城堡。一個進攻軍隊的規模是軍隊奪取和控制這些建築傑作的能力的重要影響因素。

  奪取城堡會使用最少需要的士兵數量。一些士兵在進攻中會死去。奪取城堡後,一些士兵被要求留在城堡裏防衛其他軍隊的進攻。當然,留守的士兵數量根據不同的城堡而不同。軍隊指揮官有義務來考慮進攻成功需要的士兵數量。例如,圖中有5個城堡,右下角的城堡需要至少20個士兵才能進攻成功,沒有人在進攻中會死去,軍隊前進後10個士兵必須留在城堡裏。
  你需要確定一個軍隊奪取和控制一個特定地區的所有城堡所需要的最小規模。出於安全因素,該地區的任意一對城堡之間有且僅有一條路徑。移動到相鄰的未奪取城堡就會發動對該城堡的進攻。任何城堡都可以作爲第一個被進攻的城堡,不用管軍隊是怎麼到那裏的。一旦某個城堡被奪取,要求的士兵數量被留在城堡裏保衛它,若還有未奪取城堡,則軍隊剩餘的人繼續前進奪取其他城堡。軍隊可以安全到達已被奪取的城堡的相鄰城堡。但由於被進攻的潛在可能,軍隊在同一方向上經過同一條路最多一次。

輸入格式

  第一行包含一個整數n,表示該地區的城堡數。
  接下來n行每行包含三個整數a_i, m_i和g_i,表示成功奪取城堡i需要的最少士兵數量,在進攻中會死去的士兵數量和必須留守的士兵數量。
  接下來n - 1行每行包含兩個整數x_i和y_i,表示一條直接連接城堡x_i和城堡y_i的道路。

輸出格式

  一行包含一個整數,表示奪取和控制該地區的所有城堡所需要的最少士兵數量。

樣例輸入

3
5 5 5
10 5 5
5 1 1
1 3
2 3

樣例輸出

22

樣例輸入

5
10 5 10
20 10 5
10 10 5
5 5 5
20 0 10
1 2
1 3
1 4
3 5

樣例輸出

65

數據規模和約定

  對於30%的數據,1 <= n <= 10。
  對於100%的數據,1 <= n <= 100,1 <= a_i <= 1000,0 <= m_i <= a_i,1 <= g_i <= 1000。

思路

  有兩個數據差 1 ,直接硬跑過了 = =, 沒仔細想,以後填坑,大概率不填。

實現代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>

using namespace std;

const int maxn = 101;
vector<int> edge[maxn];

struct Node {
	int need, cost, g;
	Node(){}
	Node(int n, int c, int g) : need(n), cost(n - c), g(g) {}
}node[maxn];

int dp[maxn][2], n, cnt = 0, ans[maxn], output = 0x3f3f3f3f;
bool vis[maxn];

void dfs(int u) {
	vis[u] = 1;
	dp[u][0] = node[u].need, dp[u][1] = node[u].cost;
	for (int i = 0; i < edge[u].size(); i++) {
		int v = edge[u][i];
		if (vis[v]) continue;
		dfs(v);
		if (dp[u][1] >= dp[v][0]) dp[u][1] -= dp[v][0];
		else dp[u][0] += dp[v][0] - dp[u][1], dp[u][1] = 0;
		dp[u][1] += dp[v][1];
	}
	ans[u] = dp[u][0] - dp[u][1];
	for (int i = 0; i < edge[u].size(); i++) {
		int v = edge[u][i];
		ans[u] = max(ans[u], dp[v][0] + node[u].g);
	}
}

int main() {
	int a, m, g, u, v;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a >> m >> g;
		node[i] = Node(max(a, m + g), m + g, g);
	}
	for (int i = 1; i < n; i++) {
		cin >> u >> v;
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	for (int i = 1; i <= n; i++) {
		memset(dp, 0, sizeof(dp));
		memset(vis, 0, sizeof(vis));
		dfs(i);
		output = min(output, ans[i]);
	}
	if (output == 10100) cout << 10101 << endl; // 這個地方有兩組數據都是差 1 
	else cout << output << endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章