题目描述
在一个地图上有 N (N≤20) 个地窖,每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。
输入格式
有若干行。
第 1 行只有一个数字,表示地窖的个数 N。
第 2 行有 N 个数,分别表示每个地窖中的地雷个数。
第 3 行至第 N+1 行表示地窖之间的连接情况:
第 3 行有 n−1 个数(0 或 1),表示第一个地窖至第 2 个、第 3 个 … 第 n 个地窖有否路径连接。如第 3 行为 11000⋯0,则表示第 1 个地窖至第 2 个地窖有路径,至第 3 个地窖有路径,至第 4 个地窖、第 5 个 … 第 n 个地窖没有路径。
第 4 行有 n−2 个数,表示第二个地窖至第 3 个、第 4 个 … 第 n 个地窖有否路径连接。
……
第 n+1 行有 1 个数,表示第 n−1 个地窖至第 n 个地窖有否路径连接。(为 0 表示没有路径,为 1 表示有路径)。
输出格式
第一行表示挖得最多地雷时的挖地雷的顺序,各地窖序号间以一个空格分隔,不得有多余的空格。
第二行只有一个数,表示能挖到的最多地雷数。
输入输出样例
输入
5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1
输出
1 3 4 5
27
代码
无注释版
#include<bits/stdc++.h>
using namespace std;
int a[55][55],w[55],f[55],c[55];
int l,k,maxx;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>w[i];
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
cin>>a[i][j];
}
}
f[n]=w[n];
for(int i=n-1;i>=1;i--){
l=0,k=0;
for(int j=i+1;j<=n;j++){
if(a[i][j]&&f[j]>l){
l=f[j];
k=j;
}
}
f[i]=l+w[i];
c[i]=k;
}
k=1;
for(int j=2;j<=n;j++){
if(f[j]>f[k]) k=j;
}
maxx=f[k];
cout<<k;
k=c[k];
while(k!=0){
cout<<" "<<k;
k=c[k];
}
cout<<"\n";
cout<<maxx;
}
有注释版
#include<bits/stdc++.h> // 引入标准库,包含常用的C++库
using namespace std; // 使用标准命名空间
int a[55][55], w[55], f[55], c[55]; // a 为地窖之间的连接矩阵,w 存储每个地窖中的地雷数,f 存储最大挖到的地雷数,c 存储最优路径
int l, k, maxx; // l 用来存储当前路径的最大地雷数,k 用来存储当前地窖的最优路径,maxx 存储最大地雷数
int main() {
ios::sync_with_stdio(false); // 优化输入输出性能
cin.tie(0); // 绑定输入输出流
cout.tie(0); // 绑定输入输出流
int n; // 地窖的数量
cin >> n; // 输入地窖的数量
// 读取每个地窖的地雷数
for (int i = 1; i <= n; i++) {
cin >> w[i]; // w[i] 表示第 i 个地窖的地雷数量
}
// 读取地窖之间的连接关系
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
cin >> a[i][j]; // a[i][j] 为 1 表示地窖 i 和地窖 j 有连接,0 表示没有连接
}
}
// 初始化 f[n] 为最后一个地窖的地雷数,因为从地窖 n 开始挖只能得到地窖 n 的地雷数
f[n] = w[n];
// 从倒数第二个地窖开始,逆向计算每个地窖的最大地雷数
for (int i = n - 1; i >= 1; i--) {
l = 0; // l 用来记录从地窖 i 开始的最大挖到的地雷数
k = 0; // k 用来记录最大地雷数对应的下一个地窖
for (int j = i + 1; j <= n; j++) {
// 如果地窖 i 和地窖 j 有连接且从地窖 j 挖到的地雷数大于 l(即当前最大地雷数)
if (a[i][j] && f[j] > l) {
l = f[j]; // 更新 l 为从地窖 j 能挖到的最大地雷数
k = j; // 更新 k 为当前最优路径的地窖 j
}
}
// 计算从地窖 i 挖到的最大地雷数(包括地窖 i 自己的地雷数)
f[i] = l + w[i];
c[i] = k; // 记录从地窖 i 挖到最大地雷数后,下一步最优路径为地窖 k
}
// 从地窖 1 开始,寻找最大地雷数对应的地窖
k = 1; // 假设地窖 1 是最大地雷数的起始地窖
for (int j = 2; j <= n; j++) {
if (f[j] > f[k]) k = j; // 找到最大地雷数的地窖 k
}
// 输出最大地雷数路径的第一个地窖
maxx = f[k]; // 最大地雷数
cout << k; // 输出地窖 k
// 输出从地窖 k 开始的路径
k = c[k]; // 从最优路径的下一个地窖开始
while (k != 0) {
cout << " " << k; // 输出路径上的地窖
k = c[k]; // 继续输出下一步最优路径
}
cout << "\n"; // 输出换行符
// 输出最大地雷数
cout << maxx;
}