HDU 1007 分治

If not now,When?If not me,Who?

 

看了别人的代码,感觉又学到了很多东西,本渣渣是第一次接触分治。。。

收获:

1:首先是sort()函数的应用。自己定义排序的大小,cmp和cmp2的传入的参数类型都是不一样的,很好的处理了不同的情况。

2:分治递归求解的思想:

在这道题目中就是把点按照x,y轴的顺序的分成两堆。找出两堆中最小的距离,然后再找出两堆点之间的最小距离,进行比较。

(两堆点各自的最小距离的求解是利用递归的思想,二分再递归,二分再递归,一直到left+1=right或者left=right,最终得到最小的距离t。两堆点之间的最小距离的求解,就是先筛选,两堆之间离mid点x轴小于t的点,将它们的序号储存在dp[]数组里面。然后利用cmp2进行sort,按照y轴的顺序排列,找到dis小于t的t3,更新t)

int mid=(left+right)/2;
	double t1=GetClosePair(left,mid);
	double t2=GetClosePair(mid+1,right);
	double t=t1<t2? t1:t2;

分治的思想:当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。(例如:经典的成16枚硬币的问题,其中有一枚硬币的重量跟别的是不一样的,这个时候可以二分求解) 

 

 3:dp[]是一个装点序号(x轴距离mid的距离小于t的点)的数组。后面再筛选两点之间y轴坐标

小于t的时候,访问的是p[dp[i]],但是这个地方错了好久都没有看出来。

 

 

然后放上代码,基本上是参照一个大佬做出来的。

#include <iostream>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdio>
using namespace std;
#define MAX 2147483647


struct Point{
	double x;
	double y;
}p[100010];
int dp[100010];

bool cmp(Point a,Point b)//按照x轴排序 
{
	if(a.x!=b.x)	return a.x<b.x;
	else 			return a.y<b.y;
}

bool cmp2(int a,int b)//按照y轴排序
{
	return p[a].y<p[b].y;
}

double dis(int a,int b)//返回两点之间的距离
{
	return sqrt( (p[a].x-p[b].x)*(p[a].x-p[b].x)+(p[a].y-p[b].y)*(p[a].y-p[b].y) );
}

double GetClosePair(int left,int right)
{
	if(left==right){
		return MAX;
	}
	if(left+1==right){
		return dis(left,right);
	}
	int mid=(left+right)/2;//找到终点后,递归求解
	double t1=GetClosePair(left,mid);//
	double t2=GetClosePair(mid+1,right);
	double t=t1<t2? t1:t2;
	
	int i,j,temp=0;
	for(i=left;i<=right;i++){
		if(fabs(p[i].x-p[mid].x) <= t ){
			dp[temp++]=i;
		}
	}
	sort(dp,dp+temp,cmp2);
	for(i=0;i<temp;i++){
		for(j=i+1;j<temp && fabs(p[dp[i]].y-p[dp[j]].y) < t;j++){
				double t3=dis(dp[i],dp[j]);
				if(t3<t) t=t3;
		}
	}
	return t;
}

int main()
{
	int T;
	while(cin >> T &&T)
	{
		int i;
		for(i=0;i<T;i++){
			scanf("%lf %lf",&p[i].x,&p[i].y);
		}
		sort(p,p+T,cmp);//先按照x轴从左到右排序
		double t=GetClosePair(0,T-1);
		cout << fixed << setprecision(2) << t/2 << endl; 
		
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值