CodeForces - 1408D D. Searchlights(思维)

题意:

给出 n n n个人的坐标 ( a , b ) (a,b) (a,b) m m m个监测点的坐标 ( c , d ) (c,d) (c,d),如果 a ≤ c a \leq c ac 并且 b ≤ d b \leq d bd 则被监测到,每次操作可以将所有人整体向上下左右任意一个方向移动一个,问最少要多少次操作才能使得所有人不被监测到。

题解:

最优操作肯定是只能向上或向右的。考虑枚举向右的次数,那么我们就得计算出移动完后还会被监测的人还需向上移动的最大值。但是直接暴力计算肯定不行。所以要预处理。

d p [ x ] dp[x] dp[x] 表示向右移动 x x x 步才能不被监测的人,只向上移动的步数的最大值。那么当枚举向右移动 i i i 步,那么所有 x > i x > i x>i 的人都只能向上移动,所以此时要计算 max ⁡ j = i + 1 1 e 6 d p [ j ] \max\limits_{j=i+1}^{1e6} dp[j] j=i+1max1e6dp[j] 。那么只要再预处理 d p dp dp 的后缀最大值即可。

代码:

#pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int MAXN=1e6+5;
const int inf=0x3f3f3f3f;
struct node
{
    int a,b;
}f[MAXN];
int c[MAXN],d[MAXN];
int dp[MAXN];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>f[i].a>>f[i].b;
    }
    for(int i=1;i<=m;i++){
        cin>>c[i]>>d[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(f[i].a<=c[j])
            {
                dp[c[j]-f[i].a+1]=max(dp[c[j]-f[i].a+1],d[j]-f[i].b+1);
            }
        }
    }
    for(int i=1e6;i>=0;i--)
    {
        dp[i]=max(dp[i+1],dp[i]);
    }
    int ans=1e9;
    for(int i=0;i<=1e6;i++)
    {
        ans=min(ans,i+dp[i+1]);
    }
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值