2020杭电多校第7场 1007 Game
原题链接
题意:
有一个二维平面,上面有n个点,在第一个点上有一颗石头。现在有两个人做游戏,他们轮流移动石头,
第一次移动的时候可以将石头移动到平面上的其他任何的点上。之后的每次移动,可以将石头移动到比上次移动距离更远的点上。
当轮到某人时,他无法再移动石头,则判他为输。
做法:
我们先考虑第一步:当前是第一个点,如果说第一个点和其他的某个点是平面中最长距离的点对,则先手必胜。
同样:也就是说,如果当前点在目前平面上和其他某个点能组成为最长点对的话,当前这个人必胜。
那么我们可以反着处理一下,在计算所有点对之间的距离后,按照距离从大到小排序之后遍历所有点对,如果我们在遍历点对的途中,
发现点1已经被遍历过了并且剩下的点的个数大于1,则先手必胜,否则必败。
#include <bits/stdc++.h>
#define DEBUG
#define d1(x) std::cout << #x " = " << (x) << std::endl
#define d2(x, y) std::cout << #x " = " << (x) << " ," #y " = " << (y) << std::endl
#define disp(arry, fr, to) \
{ \
std::cout << #arry " : "; \
for(int _i = fr; _i <= to; _i++) std::cout << arry[_i] << " "; \
std::cout << std::endl; \
}
#define ed end()
#define bg begin()
#define mkp make_pair
#define pb push_back
#define v(T) vector<T>
#define all(x) x.bg,x.ed
#define newline puts("")
#define si(x) ((int)x.size())
#define rep(i,n) for(int i=1;i<=n;++i)
#define rrep(i,n) for(int i=0;i<n;++i)
#define srep(i,s,t) for(int i=s;i<=t;++i)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 5e6+10;
const int inf = 0x7f7f7f7f;
const ll inf_ll = 1ll*inf*inf;
const int Mod = 1e9+7;
const double eps = 1e-7;
int n;
double a[2010],b[2010];
struct node{
int x,y;
double dis;
}e[maxn];
double cdis(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
bool cmp(node a,node b){return a.dis>b.dis;}
bool vis[maxn];
int main(){
// freopen("1.out","w",stdout);
int T;
scanf("%d",&T);
for(int _=1;_<=T;_++)
{
scanf("%d",&n);
rep(i,n){
scanf("%lf%lf",&a[i],&b[i]);
vis[i]=0;
}
int cnt=0;
rep(i,n){
for (int j=i+1;j<=n;j++){
double dis=cdis(a[i],b[i],a[j],b[j]);
e[++cnt].dis=dis;
e[cnt].x=i;
e[cnt].y=j;
}
}
sort(e+1,e+cnt+1,cmp);
// rep(i,cnt){
// d2(i,e[i].dis);
// }
int flag=0;
int sum = n;
rep(i,cnt){
int x=e[i].x,y=e[i].y;
if(!vis[x] && !vis[y]){
vector<int>G;
int j = i;
while(j<=cnt && e[j].dis == e[i].dis){
int u=e[j].x,v=e[j].y;
if(vis[u] || vis[v]){
j++;continue;
}
G.push_back(u),G.push_back(v),j++;
}
i=j-1;
for (auto v : G){
vis[v]=1;
}
if(vis[1] == 1 && sum > 1) flag=1;
sum-=G.size();
}
if(flag) break;
}
// d1(flag);
if(flag) puts("YES");
else puts("NO");
}
return 0;
}