营救家人(save)

包河区2020年信息学竞赛试题

题目描述 Description

北境统领史塔克家族的部分家人被兰尼斯特家族软禁。为了营救家人,北境之王罗柏 · 史塔克准备率领众多北境领主攻伐兰尼斯特家族。北境共有n个领主,每个领主都住在自己的城堡里面,每个城堡都屯有一定数量的士兵。 由于地形、经济条件等原因,只有部分城堡之间有道路连接。罗柏 · 史塔克想汇总领主的兵力,他可以选择从任一城堡出发,并沿着道路向后面的城堡进发(从第i号城堡只能向第i+1到第n号城堡进发),当没有后续城堡时,完成兵力的集中。请你设计一个汇总兵力的方案,使得罗柏.史塔克能集中最多的兵力。

输入描述 Input Description

有n+1行。第1行只有一个数字,表示城堡的个数n。第2行有n个数,分别表示每个城堡中的士兵个数。第3行至第n+1行表示城堡之间的道路连接情况,0表示没有道路,1表示有道路。如第3行有n-1个数,表示第1个城堡至第2个、第3个、……、第n个城堡是否有道路连接。后面以此类推。

输出描述 Output Description

有两行数据。第一行表示最优方案中访问城堡序号的排列,各序号间以一个空格分隔,没有多余的空格。第二行只有一个数,表示能集中到的最多的士兵数量。

样例输入 Sample Input

3 100 150 200 1 1 0

样例输出 Sample Output

1 3 300

数据范围及提示 Data Size & Hint

最优方案:罗柏 · 史塔克从1号城堡出发,然后到3号城堡,一共能集中300个士兵。

n<=20,其他数据都在int范围以内。

这道题使用了动态规划

代码:

#include<iostream>
#include<vector>
using namespace std;
int n, t, ans;
#define MAXN 25
int a[MAXN];
int ans_pos;
int f[MAXN];//从第i个城堡出发,所能得到的最大兵力
int path[MAXN];
vector<int> g[MAXN];
vector<int> b;
int dfs(int x) {
	if (f[x] != 0) {
		return f[x];
	}
	int maxn = 0;
	for (int i = 0; i < g[x].size(); i++) {
		int v = g[x][i];
		int tmp = dfs(v);
		if (tmp > maxn) {
			maxn = tmp;
			path[x] = v;
		}
	}
	f[x] = maxn + a[x];
	return maxn + a[x];
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}

	//建图
	for (int i = 1; i <= n; i++) { //第i个城堡 -- 其后的所有城堡
		for (int j = i + 1; j <= n; j++) { //j表示第i个城堡其后的所有城堡
			cin >> t;
			if (t == 1) {// i-->j 存在边
				g[i].push_back(j);
			}
		}
	}
	//建图
	for (int i = 1; i <= n; i++) {
		int tmp = dfs(i);
		if (tmp > ans) {
			ans = tmp;
			ans_pos = i;
		}
	}
	int pos = ans_pos;
	while (path[pos] != 0) {
		cout << pos << " ";
		pos = path[pos];
	}
	cout << pos << endl << ans;
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值