题意:
给出 n n n个人的坐标 ( a , b ) (a,b) (a,b)和 m m m个监测点的坐标 ( c , d ) (c,d) (c,d),如果 a ≤ c a \leq c a≤c 并且 b ≤ d b \leq d b≤d 则被监测到,每次操作可以将所有人整体向上下左右任意一个方向移动一个,问最少要多少次操作才能使得所有人不被监测到。
题解:
最优操作肯定是只能向上或向右的。考虑枚举向右的次数,那么我们就得计算出移动完后还会被监测的人还需向上移动的最大值。但是直接暴力计算肯定不行。所以要预处理。
设 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);
}