【1错笔记】回旋星空——妙用排序

回旋星空

题目描述:

曾经有两个来自吉尔尼斯的人(A和C)恋爱了,他们晚上经常在一起看头上的那片名为假的回旋星空,

有一天他们分手了,A想通过回旋星空测量他们之间的复合指数,测量的规则是,

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

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

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

A花了一晚上终于把整片星空映射到了一张二平面图上,由于星星太多以至于A有点懵逼,所以

你能帮帮他吗,要不然他可能真的WA的一声哭了出来。

输入描述:

第一行一个整数T(T<=10),表示组数

对于每组数据有一个n,表示有n个小星星(0< n < 1000)

接下来跟着n行,每行跟两个整数xi和yi表示每个星星的坐标(-10000< xi, yi<10000)

输出描述:

对于每组数据,如果没有找到回旋图标输出”WA”,否则输出找到图标个数

示例:

输入:

2
2
1 0
0 1
3 
1 0
0 1
0 0

输出:

WA
2

备注:
没有重复的星星,且选中的三个星星是互相不一样的(即下标不同)
欧氏距离即直线距离


问题分析:

这道题好像是我接触的第一道关于图形计算的问题,不知道有没有涉及图形学的知识,先看看题。

审完题第一个问题就是不知道如何储存数据,不知道怎么一对一对的储存数据,看了别人的技术博才顿然醒悟,原来还有结构体这个东西。现在回想起来也是,做了那么多题目,对然结构体用过,但都不是自己主动使用的,大多都是在学语法或算法时根据书本、视频的代码接触它的使用方法的。

果然,实践才是最好老师,以后在储存一套一套的数据时我想就应该不会忘记它了。

第二个迎面而来的问题是不知道如何去count计数这个不同的回旋图形。参考了别人的代码后才发现函数的妙用,哎,虽然都是熟悉的东西,但是就是想不到,只能看了之后说一句:“啊!还能这么用啊!”

这道题给我最大的收获应该就是排序的妙用吧,其实在之前的一道题目中就已经有感悟到了,它不仅仅是在你需要对输出的结果排序时才被使用的,在某些题目的过程中使用排序先整理一下数据会对你计算和操作有巨大的帮助,虽然在这道题和之前的一道题中,排序都不是最核心和主要(相对而言)的算法,但却是尤为重要和化简的一环。


AC代码:

#include <stdio.h>
#include <string.h> 

//用结构体储存一组一组的点坐标 
struct point{
	int x,y;
}; 
//在函数外定义储存长度的数组 因为全局变量默认初始化
int dis[10000];
int i, j, k;

//函数主体在下面,为了减少复杂度,用快速排序而不用冒泡排序。 
void quicksort ( int l, int r );

//计算两点距离的函数,虽然简短但还是写成函数模式有利于理解和操作。 
int distance ( int x1, int y1, int x2, int y2 );

int main()
{
	//申明变量 
	int T, n;
	struct point star[10000];
	int sum = 0;
	int cnt = 0;
	
	

	scanf ( "%d", &T );
	while(T--)
	{
		//读入数据 
		scanf ( "%d", &n );
		sum = 0;
		for ( i=0; i<n; i++ )
		{
			scanf ( "%d %d", &star[i].x, &star[i].y );
		}
		
		//遍历结构体,寻找每一个点到另外一个点的距离。 
		for ( i=0; i<n; i++ )
		{
			//这一步至关重要,每次寻找都要归零 
			cnt = 0;
			memset ( dis, 0, sizeof(dis) );
			
			for ( j=0; j<n; j++ )
			{
				dis[cnt] = distance ( star[i].x, star[i].y, star[j].x, star[j].y );
				cnt++;
			}
			
			//对每一个点的所有距离数组进行从小到大的排序 
			quicksort ( 0, cnt-1 );
			
			//因为上面j从0开始,故数组最小值肯定为0,所以就直接k为1开始,也避免了k-1越界 
			for( k=1; k<cnt; k++ )
			{
				//因为由题可知 (i,j,k)和(k,j,i)被认为是两个不同的回旋图标
				//故如果距离相等 答案就要+2 
	  			if(dis[k] == dis[k-1])
				  	sum += 2;
			}

  		}
    	if(sum==0)printf("WA\n");
    	else printf("%d\n",sum);	
	}
	return 0;
} 

void quicksort ( int left, int right )
{
	int i, j, t, temp;
	

	if ( left>right ) return;
	
	i = left;
	j = right;
	temp = dis[left];
	
	while ( i!=j )
	{
		while ( dis[j]>=temp && i<j )
			j--;
		while ( dis[i]<=temp && i<j )
			i++;
		
		if ( i<j )
		{
			t = dis[i];
			dis[i] = dis[j];
			dis[j] = t;
		}
		
	}
	
	dis[left] = dis[i];
	dis[i] = temp;
	
	quicksort ( left, i-1 );
	quicksort ( i+1, right );

}

int distance ( int x1, int y1, int x2, int y2 )
{
	return ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值