只是记录一下
debug快把我干死了 搞了一个小时才想明白为什么总有一组数据通过不了
没有考虑到1号点跟哪个酒窖之间都没有路径的情况 并且1号点自身地雷数量是最大的
我们的循环只考虑到从2号点开始的情况
所以我们需要给最大路径和最大路径最后一个点的编号都赋初值为1号酒窖
//本题f[i]表示以第i个地窖结尾所挖到的地雷最大值
//思路对了 但代码还是没写出来
#include <bits/stdc++.h>
using namespace std;
const int N = 210;
int n;
int res;
int pos; //记录挖到最大地雷数的最后一个地窖编号
int g[N][N], w[N];
int f[N];
int p[N]; //我们利用求祖宗节点的方式 输出挖地雷的路径 用数组存一下每个数的祖宗节点
void find(int x) //找挖到最大地雷数路径上的地窖编号 输入的是末尾的地窖编号
{
if(p[x]) find(p[x]); //如果x有前驱节点 继续搜 直到搜到祖宗节点 祖宗节点的p[]=0;然后就可以向下执行 ;执行后由于p[祖宗]==0,函数不断返回0,从而可以输出路径上所有地窖编号
if (p[x] == 0) printf("%d", x);
else printf(" %d", x); //输出当前节点
}
int main()
{
// ios::sync_with_stdio(false); //本题输入输出流取消关联后还会影响答案输出 神奇 要把最后的代码改成这样才能重开一行printf("\n%d\n", res);
// cin.tie(0);
// cout.tie(0);
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
int x, y;
for (int i = 1; i <= n - 1; i ++ )
{
for (int j = i + 1; j <= n; j ++ )
{
scanf("%d", &g[i][j]) ;
//cout << g[i][j] << endl;
}
}
for (int i = 1; i <= n; i ++ ) f[i] = w[i]; //初始化f[i]初始值是其自身能挖到的地雷个数
res = f[1];
pos = 1;
for (int i = 2; i <= n; i ++ ) //因为地窖1不能作为结尾的点,所以从第2个点遍历到n号地窖
{
for (int j = i; j > 0; j -- ) //能在i号点前的地窖肯定编号比i小
{
if (g[j][i] == 1 && f[j] + w[i] > f[i]) //判断当前从j号地窖到i号地窖有没有路径且是否大于当前最大值
{
f[i] = f[j] + w[i];
//cout << f[i] << endl;
p[i] = j; //记录路径的关键一步!记录此时路径i的上一个节点是j
}
}
if (res < f[i]) //每次记录完以i结尾的路径产生的地雷最大值后,与res比较,如果当前地雷数更大
{
res = f[i];
pos = i; //记录当前结尾地窖编号i
}
}
find(pos);
//cout << endl;
printf("\n%d\n", res);
//cout << f[2] << endl;
return 0;
}