广东工业大学ACM程序设计大赛 回旋星空

题目链接:点击打开链接

题意:

计算回旋图标的个数,即选中三颗星星,分别作为回旋图标的起点,拐点和终点,假设现在有三个

星星分别为i,j,k,如果d(a[i],a[j]) == d(a[j],a[k])则表示找到了一个回旋图标,其中d(x,y)表示这两个点的欧氏距离

为了给它很大的希望(i,j,k)和(k,j,i)被认为是两个不同的回旋图标

为了形象解释题意。灵魂画师已上线。

题解:先看一下最直观的解法。三层for循环去解决。第一层for循环去枚举第二个 i 星星 ,第二层for循环去枚举其他点 j 到 i 点的距离,第三层for循环去找 找有没点 k ,让did(i,j) == dis(i,k);看一眼数据范围1e4.n的三次方的时间复杂度绝对过不去。

那么考虑一下优化。思考一下绝对省不掉的步骤,就是计算任意两个点之间的距离。那么我们能做什么呢?

既然不能枚举3个点。那么我们换个思考方式,就是枚举回旋的图标的终点。也就是枚举中间点。若这个中间点与的其他点的距离有两个或者两个以上相等。说明这个点可以作为回旋图标的中间点。然后在考虑一个问题,如何去判断距离之间相等。for循环一个一个比较么?肯定不对啊。这样时间复杂度有上到n的三次方了。并且我们还有知道相等的距离有多少个。所以桶排序这种数据结构就用上了。这时候可能就有细心的同学可能会问。距离有可能成为double类型的数据么。数组没法记录啊。

想的很好。就是会出现这个问题。遇到问题就去解决问题。我们map一下不就解决了。

把浮点型的数字对应成一个int的数字。(场上想出来的骚操作=-=)。

最后统计出来那些数字相等之后。就变成总n个物品中取两个的问题。当然了结果要*2。因为对于同一个正过来是回旋图标,反过来也是回旋图标。

最后看代码实现:

#include <iostream>  
#include <cstring>  
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;  

const int maxn = 1005;
struct node{
	int x;
	int y;
}Point[maxn];

double dis(node a,node b){
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y) *(a.y - b.y));
}
int main(){
	int z;
	cin >> z;
	while(z--){
		int n ;
		cin >> n;
		for(int i = 0 ; i < n ; i ++){
			scanf("%d%d",&Point[i].x,&Point[i].y);
		}
		if(n < 3){ // 小于3个点 绝对不会出现的 
			cout << "WA" << endl;
			continue;
		}
		int ans = 0;
		for(int i = 0 ; i < n ; i ++){
			map<double,int> mp; // 骚操作 
			int num = 0; // 把每个double型的值 对应成int 

			int res[maxn];
			memset(res,0,sizeof(res));
			for(int j = 0 ; j < n ;j ++){
				if (!mp.count(dis(Point[i],Point[j]))){ // 先判断这个数字是否出现过。没出现过 mp.count函数返回值为0。 
					mp[dis(Point[i],Point[j])] = num ++;
				}
				res[mp[dis(Point[i],Point[j])]]++; // 通桶排序 
			}
			for(int i = 0 ; i < num ; i ++){
				if(res[i] >= 2){
					ans += res[i]*(res[i]-1)/2;
				}
			}
		}
		if(ans)
		cout << ans * 2<< endl;
		else
			cout << "WA" << endl;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值