P2196 [NOIP 1996 提高组] 挖地雷

题目描述

在一个地图上有 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值