题意
蛇之王国是一个 N × N 的网格,他们最宝贵的藏品就是一个巨大的毒药库,存储在王国中央
K × K 的区域中。保证 N 和 K 都是奇数。假设网格中 (1, 1) 为左上角,(N, N) 为右下角,那么
中央的 K × K 区域的左上角格子为 ((N - K)/2 + 1,(N - K)/2 + 1)。
但有贼想要盗走这些毒药。他们没法进入王国 N × N 的领地中,但他们从可以外面射箭。这
些箭可以横穿一整行(从左至右或从右至左)或者纵跨一整列(从上至下或者从下至上)。如果箭
穿过了 K × K 的部分,一些毒药就会沾到箭上;之后这支箭飞出 N × N 的领地之后,贼就能获
得一部分毒药了。
作为蛇之王国的国王,你希望可以组织这些盗贼。你知道,如果箭射到了蛇身上,蛇身上的
鳞片会挡住箭,让它停下,但蛇不会受伤。已经有一些蛇在保卫毒药了。每条蛇占据了 N × N 网
格中连续一条线上的格子,以及一行或者一列的一部分。两条蛇可以占据相同的部分格子。如果
这些蛇可以组阻止盗走毒药,那么我们称蛇的布局是安全的。阻止盗走毒药,即无论从哪行哪列
的哪一侧射箭,要么无法经过 K × K 的部分,要么无法离开 N × N 的领地。
国王还要给众蛇安排其他任务,因此想要将尽可能多的保卫蛇调走去干别的工作,但仍然使
得剩下的蛇的布局是安全的。请你帮他求出最少得留下多少条蛇。
数据
输入的第一行包含一个整数 T,代表测试数据的组数。接下来是 T 组数据。
每组数据第一行包含三个整数 N、K 和 M,分别代表领地边长、毒药库边长,以及初始时保卫蛇的条数。
接下来 M 行,每行包含四个整数 HX[i]、HY[i]、TX[i] 和 TY[i]。(HX[i], HY[i])是第i条蛇的头部
坐标,(TX[i], TY[i]) 是第i条蛇的尾部坐标。保证这两个坐标对应的格子位于同行或同列,第i条蛇占据两个格子之间的所有格子。
1 <= T <= 4, 3 <= N <= 1e9, 1 <= K <= N - 2, N和K都是奇整数
1 <= M <= 1e5, 1 <= HX[i], HY[i], TX[i], TY[i] <= N, HX[i] = TX[i]或者HY[i] = TY[i]
K × K的区域不会被任意一条蛇占据,两条蛇占据的位置可能有重合部分
输入
2
7 3 7
1 1 6 1
1 2 3 2
5 2 5 2
2 4 2 6
6 2 6 4
5 6 5 7
7 1 7 4
7 3 7
1 1 6 1
1 2 3 2
5 2 5 2
2 6 2 6
6 2 6 4
5 6 5 7
7 1 7 4
输出
3
-1
思路:蛇不会在中间那块,所以每条蛇挡的不是上下就是左右方向,所以分别考虑,这样问题就变成了最小区间覆盖问题了,可以按左端点排序,每次选已经覆盖的区间中右端点最大的区间。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e6+5;
struct node
{
int l, r;
node(){}
node(int ll, int rr): l(ll), r(rr) {}
bool operator < (const node &a) const
{
if(l == a.l) return r > a.r;
return l < a.l;
}
}a[maxn], b[maxn];
int n, k, m, cnt1, cnt2;
bool ok;
int cal(node *c, int cnt)
{
int s = (n-k)/2+1, e = (n+k)/2;
int res = 0, p = 0;
int cur = s, Max = 0, index;
for(int i = 0; i < cnt; i++)
{
for(int j = i; j < cnt; j++)
{
if(c[j].l > cur)
break;
else
{
if(c[j].r+1 > Max)
Max = c[j].r+1, index = j;
}
}
if(!Max) { ok = 0; return 0; }
else
{
cur = Max;
res++;
i = index;
Max = 0;
if(cur > e) return res;
}
}
ok = 0;
return 0;
}
int main(void)
{
int t;
cin >> t;
while(t--)
{
ok = 1;
cnt1 = cnt2 = 0;
scanf("%d%d%d", &n, &k, &m);
for(int i = 1; i <= m; i++)
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if(x1 == x2)
{
if(y1 > y2) swap(y1, y2);
if(x1 >= (n-k)/2+1 && x1 <= (n+k)/2)
b[cnt2++] = node(x1, x2);
else
a[cnt1++] = node(y1, y2);
}
else
{
if(x1 > x2) swap(x1, x2);
if(y1 >= (n-k)/2+1 && y1 <= (n+k)/2)
a[cnt1++] = node(y1, y2);
else
b[cnt2++] = node(x1, x2);
}
}
sort(a, a+cnt1);
sort(b, b+cnt2);
int ans = cal(a, cnt1)+cal(b, cnt2);
printf("%d\n", ok ? ans : -1);
}
return 0;
}