蓝桥杯---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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章