题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。
敌国的导弹形成了立体打击,每个导弹可以抽象成一个三维空间中的点(x; y; z)。拦截系统发射的炮弹也很好地应对了这种情况,每一发炮弹也可以视为一个三维空间中的点。
但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达三维空间中任意的点,但是以后每一发炮弹到达点的坐标(x; y; z) 的三个坐标值都必须大于前一发炮弹的对应坐标值。
某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹飞来的坐标,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。注意: 所有导弹都是同时飞来的
思路
orz人生导师jpwang
前一问一个dp,f[i]表示拦截第i个可以拦截最多拦截到的导弹
f[i] = 1
f[i] = max(f[j]+1) (1 <= j < i) 且受题目限制
来考虑第二问
我们可以将i拆点为 i, i‘, 对于两个导弹i,j,若从i可以打j,那么我们就连一条(i,j‘)的边
这样就变成了一个二分图,因为我们要将全部点都达到,所以就是求一个二分图的最小路径覆盖 = 点数 - 最大匹配
跑网络流或其他算法都可以
#include <stdio.h> #include <queue> #include <algorithm> #include <cstring> #include <string> using namespace std; #define max(x, y) (x) > (y) ? (x) : (y) #define min(x, y) (x) < (y) ? (x) : (y) #define INF 0x7f7f7f7f #define fill(x, y) memset(x, y, sizeof(x)) struct edge { int x, y, z; }e[2000001]; struct arr { int to, w, next; }e1[2000001]; int n, f[10001], ls[20001], cur[20001], state[20001], S, E; inline int read() { int x=0,p=1;char ch=getchar(); while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘)p=-1;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*p; } int cmp(edge a, edge b) { return a.x < b.x ; } int maxE = 1; int add(int x, int y, int w) { e1[++maxE] = (arr) {y, w, ls[x]}; ls[x] = maxE; e1[++maxE] = (arr) {x, 0, ls[y]}; ls[y] = maxE; } int bfs(int S, int E) { queue<int> t; fill(state, 0); t.push(S); state[S] = 1; while (!t.empty()) { int now = t.front(); t.pop(); for (int i = ls[now]; i; i = e1[i].next) { if (e1[i].w > 0 && !state[e1[i].to]) { state[e1[i].to] = state[now] + 1; t.push(e1[i].to); if (e1[i].to == E) return true; } } } return false; } int find(int now, int mn) { if (!mn || now == E) return mn; int ret = 0; for (int &i = cur[now]; i; i = e1[i].next) if (state[now] + 1 == state[e1[i].to] && e1[i].w > 0) { int d = find(e1[i].to, min(e1[i].w, mn - ret)); e1[i].w -= d; e1[i^1].w += d; ret += d; if (ret == mn) break; } return ret; } int dinic() { int ans = 0; while (bfs(S, E)) { for (int i = S; i <= E; i++) cur[i] = ls[i]; ans += find(S, INF); } return ans; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) { e[i].x = read(); e[i].y = read(); e[i].z = read(); } sort(e + 1, e + n + 1, cmp); for (int i = 1; i <= n; i++) { f[i] = 1; for (int j = 1; j < i; j++) { if (e[j].x < e[i].x && e[j].y < e[i].y && e[j].z < e[i].z) f[i] = max(f[i], f[j] + 1); } } int ans = 0; for (int i = 1; i <= n; i++) { ans = max(ans, f[i]); } printf("%d\n", ans); int l = 0; for (int i = 1; i <= n; i++) for (int j = 1; j < i; j++) if (e[j].x < e[i].x && e[j].y < e[i].y && e[j].z < e[i].z) add(j, i + n, 1); S = 0; E = n * 2 + 1; for (int i = 1; i <= n; i++) { add(S, i, 1); add(i + n, E, 1); } printf("%d", n - dinic()); }
时间: 2024-10-22 23:21:13