1262:【例9.6】挖地雷
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 5894 通过数: 2829
【题目描述】
在一个地图上有n个地窖(n≤200),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径,并规定路径都是单向的,且保证都是小序号地窖指向大序号地窖,也不存在可以从一个地窖出发经过若干地窖后又回到原来地窖的路径。某人可以从任意一处开始挖地雷,然后沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使他能挖到最多的地雷。
【输入】
第一行:地窖的个数;
第二行:为依次每个地窖地雷的个数;
下面若干行:
xiyi //表示从xi可到yi,xi<yi。
最后一行为"00"表示结束。
【输出】
k1−k2−…−kv //挖地雷的顺序
挖到最多的雷。
【输入样例】
6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0
【输出样例】
3-4-5-6
34
思路:
这个题就是跟那些最大和差不多,只不过这个固定了单向通道。那我们就是在原来的基础上添加一个判断这个通道的判断标准。
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
int a[1010],dp[1010][1010],b[1010],c[1010];
using namespace std;
int main()
{
int n; cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
int x,y;
while (cin >> x >> y && x && y)
{
dp[x][y] = 1;
}
b[n] = a[n];
用逆序来做,这样好写坐标
for (int i = n - 1; i >= 1; i--)
{
int o = 0, p = 0;//o用来记录值,p用来记录坐标。
for (int j = i + 1; j <= n; j++) 来判断一个最大的值得一个通道坐标以及值
{
if (dp[i][j] && b[j] > o)
{
o = b[j];
p = j;
}
}
b[i] = a[i] + o;//求此道值
c[i] = p;//用c[i]记录坐标
}
int maxx = 0; int z;
for (int i = 1; i <= n; i++)
{
if (b[i] > maxx)
{
maxx = b[i]; z = i;
}
}最大值一定是终点坐标;
cout << z;
z = c[z];这个处理坐标的方式很巧妙;
while (z != 0)
{
cout << "-" << z; z = c[z];
}
cout << endl;
cout << maxx << endl;
}
1260:【例9.4】拦截导弹(Noip1999)
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 9076 通过数: 3418
【题目描述】
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
【输入】
输入导弹依次飞来的高度。
【输出】
第一行:最多能拦截的导弹数;
第二行:要拦截所有导弹最少要配备的系统数。
【输入样例】
389 207 155 300 299 170 158 65
【输出样例】
6
2
思路 :第一问好求 就是最长序列 第二问就是来处理系统数
这个导弹能不能打。得去所有的系统遍历一遍,找出来其中最小的一个,如果找不到,就添加一个系统并且把此导弹的值给系统的值。
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
int i, j, k, x, n, maxx, m, a[1000], b[1000], h[1000];
i = 1; n = 0; m = 0;
memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); memset(h, 0, sizeof(h));
while (cin >> a[i])
{
maxx = 0;
for (j = 1; j <= i - 1; j++)//计算前i-1个导弹最佳拦截的方案
if (a[j] >= a[i])
if (b[j] > maxx) maxx = b[j];
b[i] = maxx + 1;//在前i-1个导弹最佳方案上+1;
if (b[i] > m) m = b[i];
x = 0;
for (k = 1; k <= n; k++)//计算由哪一套系统拦截导弹
if (h[k] >= a[i])
if (x == 0) x = k;
else if (h[k] < h[x]) x = k;
//如果有多套系统可拦截,则选择上一次拦截高度最低的!
if (x == 0)//新增一套导弹拦截系统
{
n++; x = n;
}
h[x] = a[i];
i++;
}
cout << m << endl << n << endl;
}