包河区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;
}