[NOIP1996 提高组] 挖地雷
题目描述
在一个地图上有 N ( N ≤ 20 ) N\ (N \le 20) N (N≤20) 个地窖,每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。
输入格式
有若干行。
第 1 1 1 行只有一个数字,表示地窖的个数 N N N。
第 2 2 2 行有 N N N 个数,分别表示每个地窖中的地雷个数。
第 3 3 3 行至第 N + 1 N+1 N+1 行表示地窖之间的连接情况:
第 3 3 3 行有 n − 1 n-1 n−1 个数( 0 0 0 或 1 1 1),表示第一个地窖至第 2 2 2 个、第 3 3 3 个 … \dots … 第 n n n 个地窖有否路径连接。如第 3 3 3 行为 11000 ⋯ 0 11000\cdots 0 11000⋯0,则表示第 1 1 1 个地窖至第 2 2 2 个地窖有路径,至第 3 3 3 个地窖有路径,至第 4 4 4 个地窖、第 5 5 5 个 … \dots … 第 n n n 个地窖没有路径。
第 4 4 4 行有 n − 2 n-2 n−2 个数,表示第二个地窖至第 3 3 3 个、第 4 4 4 个 … \dots … 第 n n n 个地窖有否路径连接。
……
第 n + 1 n+1 n+1 行有 1 1 1 个数,表示第 n − 1 n-1 n−1 个地窖至第 n n n 个地窖有否路径连接。(为 0 0 0 表示没有路径,为 1 1 1 表示有路径)。
输出格式
第一行表示挖得最多地雷时的挖地雷的顺序,各地窖序号间以一个空格分隔,不得有多余的空格。
第二行只有一个数,表示能挖到的最多地雷数。
样例 #1
样例输入 #1
5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1
样例输出 #1
1 3 4 5
27
提示
【题目来源】
NOIP 1996 提高组第三题
#include <iostream>
//挖地雷
using namespace std;
const int N = 100;//常量
int f[N],a[N];//f最大值 a当前存储
int n, ans;//数量 最值
bool edge[N][N];//求最值
void tu()//创建图
{
for(int i=1; i<n; i++)
{
for(int j=i+1; j<=n; j++)
{
cin>>edge[i][j];
}
}
}
void dp()//动态规划
{
for(int i=1; i<=n; i++)
{
f[i]= a[i];
for(int j=1; j<i; j++)
{
if(edge[j][i])
{
if(f[j]+a[i]>f[i])
{
f[i] = f[j]+a[i];
}
}
}
if(f[i]>ans) ans = f[i];
}
return;
}
int main()
{
cin>>n;
for(int i=1;i<=n; i++)
{
cin>>a[i];
}
tu();
dp();
cout<<ans;
return 0;
}
/*
1、确定状态:求什么定义什么
原问题:挖到i时,挖到的最多的雷
f[i]:挖到i时最多的地雷存储到f[i]种
2、状态转移方程
f[i] = max(f[i],f[j]+a[i]);
当前的最大值和当前的值与前一个最大值之和进行比较
3、边界值
那些由状态转移方程计算不出来的状态就是边界
j到i无路时
f[i] = a[i]
4、填表次数 由左向右
流程图:定义变量和数组--输入数据--建图--利用动态规划--输出结果
*/