列表

详情


NC204780. 二维动点

描述

一个二维平面上有n个点(a_i,b_i),在一次移动中,你可以选择一个不和当前所在位置重叠的点,然后可以移动到当前所在位置和选择的点构成的直线上的任何一个位置;每次询问一个点(x,y),求出从(0,0)到达(x,y)所需要的最少移动次数,无解输出-1

输入描述

第一行为两个数n,q
接下来n行,每行两个数a_i,b_i,表示一个点的坐标
接下来q行,每行两个数x_i,y_i,表示询问一个目标点

输出描述

共q行,每行一个整数,表示到达目标点所需要的的最少移动次数,无解输出-1

示例1

输入:

2 3
1 2
2 1
3 3
2 4
2 2

输出:

3
1
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 385ms, 内存消耗: 14604K, 提交时间: 2020-06-12 19:29:45

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mp make_pair
#define y1 ____y1
const int N=100005;
int n,m,x,y,cnt,tot;
map<pair<int,int> ,int> Map;
int a[N],b[N];
inline int pd(int x1,int y1,int x2,int y2){
	return x1*y2-x2*y1!=0;
}
signed main(){
	scanf("%lld%lld",&n,&m);
	for (int i=1;i<=n;i++){
		scanf("%lld%lld",&x,&y);
		if (!x&&!y)continue;
		int d=__gcd(x,y);
		x/=d;y/=d;
		cnt+=!Map[mp(x,y)];
		Map[mp(x,y)]=1;
		a[++tot]=x*d;b[tot]=y*d;
	}
	while (m--){
		scanf("%lld%lld",&x,&y);
		if (!x&&!y){
			puts("0");
			continue;
		}
		int d=__gcd(x,y);
		x/=d;y/=d;
		if (Map[mp(x,y)])puts("1");
		else if (cnt<=1)puts("-1");
		else if (tot>2)puts("2");
		else {
			x*=d;y*=d;
			if (pd(a[1],b[1],x-a[2],y-b[2]))puts("2");
			else if (pd(a[2],b[2],x-a[1],y-b[1]))puts("2");
			else puts("3"); 
		}
	}
} 

C++11(clang++ 3.9) 解法, 执行用时: 584ms, 内存消耗: 28776K, 提交时间: 2020-06-13 10:20:29

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
map<int,map<int,int>> mp;
LL a[3],b[3];
int main(){
	int n,q,len=0;
	cin>>n>>q;
	while(n--){
		int x,y,z;
		cin>>x>>y;
		z=__gcd(x,y);
		if(!x&&!y||mp[x/z][y/z])continue;
		mp[x/z][y/z]=1;
		if(len<2)a[len]=x,b[len]=y;
		len++;
	}
	while(q--){
		int x,y,z;
		cin>>x>>y;
		z=__gcd(x,y);
		if(!x&&!y){cout<<0<<endl;continue;}
		if(mp[x/z][y/z]){cout<<1<<endl;continue;}
		if(len == 1){cout<<-1<<endl;continue;}
		if(len > 2){cout<<2<<endl;continue;}
		if(a[1]*(y-b[0])==b[1]*(x-a[0])||b[0]*(x-a[1])==a[0]*(y-b[1]))
		{cout<<3<<endl;continue;}
		cout<<2<<endl;
	}
	return 0;
}

上一题