【t042】炮击坦克

Time Limit: 1 second
Memory Limit: 128 MB

【问题描述】

在一个坐标轴上,有M辆坦克,第i辆坦克在时刻0处于pos[i](pos[i]>0),speed[i]个单位,在时刻k就处于pos[i]+speed[i]*k。
原点上有一炮台。炮台有N颗炮弹,在时刻0开始就可以发射炮弹,而且发射的顺序是你来确定的,每次只能发射一颗,一颗炮弹只能
用一次。每个炮弹都有一个休息时间rest[i],如果在某次发射了第i颗炮弹,要间隔rest[i]后才能在发射。一颗炮弹只能消灭
范围D(0到D)内的一辆坦克。
最多能消灭多少辆坦克?
【输入格式】

第一行:N,M,D(N,M≤1000)
接下来N行:rest
接下来M行:pos, speed
全部都是longint内的正整数。
【输出格式】

输出最多能消灭坦克数量。

Sample Input

3 3 3
3
2
1
4 1
1 1
2 1

Sample Output

2

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=t042

【题解】

因为每枚炮弹的攻击范围是固定的;而坦克是越来越远的;
则肯定先用休息时间短的炮弹;
确定用哪个炮弹之后;其实第i次发射的炮弹(休息时间从小到大数第i个)能够攻击到的坦克就固定了;
且i越大;那枚炮弹能够攻击到的坦克就越少;(因为坦克越来越远);
这样我们先处理出第i枚炮弹的能够攻击到哪些坦克;
从第n枚炮弹开始,倒序枚举,看看第n枚炮弹能够攻击到哪些坦克;
随便攻击一个就好;
然后是第n-1枚炮弹,看看第n-1枚炮弹能够攻击到哪些坦克(且之前没有被攻击到)那就攻击它;
….
然后计数攻击了多少个坦克就好;
第i个炮弹能够攻击到的坦克,第i-1个炮弹肯定也能攻击到;
因为i越大,能够攻击到的坦克越来越少;
所以才这样,先选那些靠后都能攻击到的坦克,这样才能尽可能地为其他靠后就不能攻击到的坦克腾出炮弹;

【完整代码】

#include <cstdio>
#include <algorithm>
using namespace std;
#define LL long long

const int MAXN = 1e3+10;

struct abc
{
    LL pos,speed;
};

LL rest[MAXN],d;
int n,m,cnt = 0;
abc a[MAXN];
bool bo[MAXN],can[MAXN][MAXN];

int main()
{
    //freopen("F:\rush.txt","r",stdin);
    scanf("%d%d%I64d",&n,&m,&d);
    for (int i = 1;i <= n;i++)
        scanf("%I64d",&rest[i]);
    sort(rest+1,rest+1+n);
    for (int i = 1;i <= m;i++)
        scanf("%I64d%I64d",&a[i].pos,&a[i].speed);
    for (int i = 1;i <= n;i++)
    {
        for (int j = 1;j <= m;j++)
            if (a[j].pos<=d)
                can[i][j] = true;
        for (int j = 1;j <= m;j++)
            a[j].pos+=rest[i]*a[j].speed;
    }
    for (int i = n;i>=1;i--)
    {
        for (int j = 1;j <= m;j++)
            if (!bo[j] && can[i][j])
            {
                bo[j] = true;
                cnt++;
                break;
            }
    }
    printf("%d
",cnt);
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626665.html