这题思想很直接,定义一个表示当前点作为起点所计算的最大值的数组,递归搜每一个阶段的最大值,最后逆序返回就完了。下面就说说想这道题遇到的坑emmmm
蒟蒻的操作通常都比较迷,勿喷hhhhh
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 2e9
#define ll long long
//
using namespace std;
const int maxn = 20 + 10;
int n;
int ans = 0;
int dl[maxn];
int tot = 0, ver[maxn * 2], nexts[maxn * 2], head[maxn];
int d[maxn], route[maxn];//dp(i) 从i出发能获得的最大数量
void add(int x, int y) {
    ver[++tot] = y;
    nexts[tot] = head[x], head[x] = tot;
}
int dp(int u) {//遍历第u个出发点
    if (d[u]) return d[u];
    int curmax = 0, foot = -1;
    for (int i = head[u]; i; i = nexts[i]) {
        int y = ver[i];//下一个节点编号为y
        if (d[y] == 0) d[y] = dp(y);
        if (d[y] > curmax) {
            curmax = d[y];
            foot = y;//更新下一个节点为y
        }
    }
    route[u] = foot;
    return dl[u] + curmax;//返回u点出发的最大值
}
int main() {
    int a, start = -1;
    cin >> n;
    memset(d, 0, sizeof(d));
    memset(route, -1, sizeof(route));//路径初始化为-1
    for (int i = 1; i <= n; i++) cin >> dl[i];
    for (int i = 1; i <= n; i++) {
        //输入每一个结点的对应的连接点
        for (int j = i + 1; j <= n; j++) {
            cin >> a;
            if (a) add(i, j);//1就加一条边
        }
    }
    for (int i = 1; i <= n; i++) {
        if (!d[i]) {
            d[i] = dp(i);
            if (d[i] > ans) {
                ans = d[i];
                start = i;//找最佳开始起点编号
            }
        }
    }
    cout << start << " ";
    while (start != -1) {//输出到-1为止
        if (route[start] != -1)
            cout << route[start] << " ";
        start = route[start];
    }
    cout << endl << ans;
    return 0;
}