#include<iostream>#include<algorithm>#include<cstring>usingnamespace std;constint N =20;int a[N], g[N][N], dp[N], Next[N];//a数组存储每个洞的地雷数量,g存储洞之间的连同情况,dp存储状态,Next存储最优解路径int n;//因为遍历某个节点的相邻节点循环要用到洞的个数n所以定义为全局变量intsolve(int x)//求解从编号为x的洞出发能挖到的地雷最多的路径上的地雷数和{if(dp[x]!=-1)return dp[x];//如果计算过则返回(因为某个位置不确定其可能没有地雷,所以0应该为有效值)int max =0;for(int i =0; i < n; i++)//找所有洞中与它相连的{if(g[x][i])//判断有没有边(自己与自己没有,图为单向,应该没有圈不用担心){int y =solve(i);//就邻接状态的值if(y > max){//记录邻接状态的最大值
max = y;
Next[x]= i;//记录一下路径!后来搜索不好求路径。}//因为求最优状态i的下一个节点如果用dp[i]-a[i]来判断某一个值能保证它是下一最优选择但不能保证它与i相连}//我是这么想的,当然现在想如果那样求判断一下就好了。测试里没有多条最优没事的。}return dp[x]= max + a[x];//赋值 返回}voidprint(int x)//直接输出也很简单哦{
cout << x +1;//输出起点,为第x+1个(我这里节点序号是从0到n-1)while(Next[x]!=-1)//只要有下一个(-1代表没有下一个,因为0可能代表下一个是0所以用-1表示){
cout <<" "<< Next[x]+1;//就输出
x = Next[x];//并且从下一个开始找}return;}intmain(){
cin >> n;//输入洞数for(int i =0; i < n; i++)//输入洞地雷数
cin >> a[i];for(int i =0; i < n -1; i++)//输入连接情况{for(int j = i +1; j < n; j++){
cin >> g[i][j];//题目说向前挖仅能选择一条路径就是说单向边}}memset(dp,-1,sizeof(dp));//没有求过的状态为-1memset(Next,-1,sizeof(Next));//路径也都设置为-1(没有下一个)int max =0, maxi =0;for(int i =0; i < n; i++)//求每一个洞的状态{int z =solve(i);if(z > max){
max = z;//记录所有洞的状态的最大值
maxi = i;//记录最优解出发点}}print(maxi);//从出发点开始输出最优解路径
cout << endl << max << endl;//输出最大值return0;}