kill
思路:
二分ans后,直接贪心暴力check。
每个人去打他能打得到的最远的怪兽。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define N 100010
using namespace std;
int n, m, S;
LL goal[N], pos[N];
bool check(LL x){
int cnt = 1;
for(int i=1; i<=m && cnt<=n; ++i)
if(abs(pos[cnt] - goal[i]) + abs(goal[i] - S) <= x)
++cnt;
return cnt == n+1;
}
int main(){
freopen ("kill.in", "r", stdin);
freopen ("kill.out", "w", stdout);
scanf("%d%d%d", &n, &m, &S);
for(int i=1; i<=n; ++i) scanf("%lld", &pos[i]);
for(int i=1; i<=m; ++i) scanf("%lld", &goal[i]);
sort(goal+1, goal+m+1);
sort(pos+1, pos+n+1);
LL l = 0, r = 1LL << 32, ans;
while(l <= r){
LL mid = (l + r) >> 1;
if( check( mid ) ) r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%lld", ans);
}
开始的时候脑抽了,写了个二分图(虽然T了30,但算法还是正确的)
二分ans后,连上满足条件的边(<=ans),然后跑二分图最大匹配,看是否可以全部匹配
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL long long
#define N 100010
using namespace std;
int n, m, S, idc = 0, timex = 0;
int head[N], pos[N], goal[N], lnk[N], vis[N];
inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9'){ x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
struct Edge{
int to, nxt;
}ed[N << 1];
inline void adde(int u, int v){
ed[++idc].to = v;
ed[idc].nxt = head[u];
head[u] = idc;
}
inline int dis(int x, int y){ return abs(pos[x] - goal[y]) + abs(goal[y] - S);}
inline int findd(int u){
for(int i=head[u]; i; i=ed[i].nxt){
int v = ed[i].to;
if(vis[v] != timex){
vis[v] = timex;
if(!lnk[v] || findd( lnk[v] )){
lnk[u] = v, lnk[v] = u;
return 1;
}
}
}
return 0;
}
bool check(int x){
int cnt = 0; idc = 0, timex = 0;
memset(head, 0, sizeof(head));
memset(ed, 0, sizeof(ed));
memset(lnk, 0, sizeof(lnk));
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
if( dis(i, j) <= x ) adde(i, j+n);
for(int i=1; i<=n; i++){
++timex;
if( !lnk[i] ) cnt += findd( i );
}
if(cnt == n) return 1;
return 0;
}
int main(){
freopen ("kill.in", "r", stdin);
freopen ("kill.out", "w", stdout);
scanf("%d%d%d", &n, &m, &S);
int l = 0, r = 0, ans = 0;
for(int i=1; i<=n; i++) pos[i] = read();
for(int i=1; i<=m; i++) goal[i] = read();
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
r = max(r, dis(i, j));
while(l <= r){
memset(vis, 0, sizeof(vis));
int mid = (l + r) >> 1;
if( check( mid ) )
r = mid - 1, ans = mid;
else l = mid + 1;
}
//if(ans == 0) ans = -1;
printf("%d\n", ans);
return 0;
}