简单算法的实现(二)

5.最近对问题

设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

 

 
#include <stdio.h>
#include <math.h>
struct piexl
{
int x;
int y;
};
int TotleNum;
struct piexl Res[1001];
float min;
void SortPiexl( int low, int high);
void CalDistance( int res, int des);
void FindBothMin( int res, int mid, int des);
void FindPartMin( int res, int des);
int main()
{
int group,i;
scanf ( "%d" ,&group);
while (group--)
{
scanf ( "%d" ,&TotleNum);
min = 0;
for (i = 0; i < TotleNum;i++)
{
scanf ( "%d%d" ,&Res[i].x,&Res[i].y);
}
SortPiexl(0,TotleNum-1);
FindPartMin(0, TotleNum - 1);
printf ( "%.4f\n" , min);
}
}
void SortPiexl( int low, int high)
{
if (low>=high)
{
return ;
}
int i = low, j = high;
struct piexl temp = Res[i];
while (i<j)
{
while (i<j && Res[j].x>=temp.x)
{
j--;
}
if (i<j)
{
Res[i] = Res[j];
}
while (i<j && Res[i].x<=temp.x)
{
i++;
}
if (i<j)
{
Res[j] = Res[i];
}
}
Res[i] = temp;
SortPiexl(low, i - 1);
SortPiexl(i+1,high);
}
void FindPartMin( int res, int des)
{
if (res+1==des)
{
CalDistance(res,des);
return ;
}
int mid;
mid = (res + des) / 2;
FindPartMin(res, mid);
FindPartMin(mid, des);
FindBothMin(res,mid,des);
}
void FindBothMin( int res, int mid, int des)
{
struct piexl left,buttom;
int i,j;
left.x = Res[mid].x-min;
buttom.x = Res[mid].x + min;
for (i = res; i < mid;i++)
{
if (Res[i].x>left.x)
{
for (j = mid + 1; j <= des;j++)
{
if (Res[j].x<buttom.x)
{
if (Res[i].y-min < Res[j].y && Res[i].y+min>Res[j].y)
{
CalDistance(i, j);
}
}
}
}
}
}
void CalDistance( int res, int des)
{
float temp = sqrt (( float )(Res[res].x - Res[des].x)*(Res[res].x - Res[des].x) + (Res[res].y - Res[des].y)*(Res[res].y - Res[des].y));
if (!min)
{
min = temp;
}
else if (min>temp)
{
min = temp;
}
}
 
第一种:看了下同学的代码!  分治法~~  懂思想,但是实现还是有点困难的!
 
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
using namespace std;
int main(){ 
 int number,i,j,n,k;
 int x[1000],y[1000]; 
 scanf("%d",&number); 
 for(k=0;k<number;k++)
 {     
  double Range=1000000;   
  double temp; 
  scanf("%d",&n); 
  for(i=0;i<n;i++)
  {
   scanf("%d %d",&x[i],&y[i]); 
        }
  
  for(i=0;i<n-1;i++)
  {
   for(j=i+1;j<n;j++)  
   {       
    temp=pow((x[i]-x[j]),2)+pow((y[i]-y[j]),2);
    if(temp<Range)  
    {     
     Range=temp;  
    }     
   }  
  }
  
 printf("%.4f\n",sqrt(Range));
}
 return 0;
}
第二种:我用的是暴力解法,就是太消耗时间了。
 

 6.凸包面积:

麦兜是个淘气的孩子。一天,他在玩钢笔的时候把墨水洒在了白色的墙上。再过一会,麦兜妈就要回来了,麦兜为了不让妈妈知道这件事情,就想用一个白色的凸多边形把墙上的墨点盖住。你能告诉麦兜最小需要面积多大的凸多边形才能把这些墨点盖住吗?
现在,给出了这些墨点的坐标,请帮助麦兜计算出覆盖这些墨点的最小凸多边形的面积。

 
#include<stdio.h>
#include<math.h>
typedef struct Point
{
int x;
int y;
}point;
point p[106];
double minares=0;
//计算三个点的面积
double area(point p1,point p2,point p3)
{
double s ;
s=p1.x*p2.y+p3.x*p1.y+p2.x*p3.y-p3.x*p2.y-p2.x*p1.y-p1.x*p3.y;
return s;
}
void sortPoints( int le, int n)
{
int f,l;
point k;
f=le;
l=n;
k=p[f];
if (f>=l)
return ;
while (f<l)
{
while (f<l&&p[l].x>=k.x)
--l;
p[f]=p[l];
while (f<l&&p[f].x<=k.x)
++f;
p[l]=p[f];
}
p[f]=k;
sortPoints(le,f-1);
sortPoints(f+1,n);
}
void getAreas( int f, int l , int n)
{
if (f==l)
{
return ;
}
int i,index=0;
double max=0;
for (i=0;i<n;i++)
{
if (i==f||i==l) //排除两个点
{
continue ;
}
double s = area(p[f],p[l],p[i])/2;
if (s>max)
{
max = s;
index = i;
}
}
if (max>0)
{
minares+=max;
getAreas(f,index,n);
getAreas(index,l,n);
}
}
int main()
{
int n,k,j;
int all;
scanf ( "%d" ,&all);
for (j=1;j<=all;j++)
{
scanf ( "%d" ,&n);
for (k=0;k<n;k++)
{
scanf ( "%d%d" ,&p[k].x,&p[k].y);
}
sortPoints(0,n-1);
minares=0;
getAreas(0,n-1,n);
getAreas(n-1,0,n);
printf ( "%.1lf\n" ,minares);
}
return 0;
}

数学好的话,这道题就好解了。。

7.PostOffice:在一个按照东西和南北方向划分成规整街区的城市里,n个居民点散乱地分布在不同的街区中。用x 坐标表示东西向,用y坐标表示南北向。各居民点的位置可以由坐标(x,y)表示。街区中任意2 点(x1,y1)和(x2,y2)之间的距离可以用数值|x1-x2|+|y1-y2|度量。居民们希望在城市中选择建立邮局的最佳位置,使n个居民点到邮局的距离总和最小。任务:给定n 个居民点的位置,编程计算n 个居民点到邮局的距离总和的最小值。

 
#include <stdio.h>
#include <math.h>
void sort( int arry[], int n)
{
int i,j,temp;
for (i=0;i<n-1;i++)
{
for (j=i+1;j<n;j++)
{
if (arry[i]>arry[j])
{
temp=arry[i];
arry[i]=arry[j];
arry[j]=temp;
}
}
}
}
int main()
{
int n,i,mid,disx=0,disy=0,result=0;
int x[10000];
int y[10000];
scanf ( "%d" ,&n);
for (i=0;i<n;i++)
{
scanf ( "%d" ,&x[i]);
scanf ( "%d" ,&y[i]);
}
sort(x,n);
sort(y,n);
mid=n/2;
for (i=0;i<n;i++)
{
disx=disx+ abs (x[i]-x[mid]);
disy=disy+ abs (y[i]-y[mid]);
}
result=disx+disy;
printf ( "%d\n" ,result);
return 0;
}

8.排列的字典序问题

n个元素{1,2,..., n }有n!个不同的排列。将这n!个排列按字典序排列,并编号为0,1,…,n!-1。每个排列的编号为其字典序值。例如,当n=3时,6 个不同排列的字典序值如下: 0 1 2 3 4 5       123 132 213 231 312 321给定n 以及n 个元素{1,2,..., n }的一个排列,计算出这个排列的字典序值,以及按字典序排列的下一个排列。

 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int a[20],vis[20];
int f( int n) //求n的阶乘。
{
int i,m=1;
for (i=2;i<=n;i++)
m*=i;
return m;
}
int main()
{
int i,j,k,n,n1,ans;
while ( scanf ( "%d" ,&n)!=EOF)
{
memset (vis,0, sizeof (vis));
ans=0;
n1=n-1; //7
for (i=1;i<=n;i++)
{
scanf ( "%d" ,&a[i]); //26458173
k=0;
vis[a[i]]=1;
for (j=1;j<a[i];j++)
if (!vis[j]) k++;
ans+=k*f(n1);
n1--;
}
cout<<ans<<endl;
for (i=n;i>=0;i--)
if (a[i]<a[i+1]) break ;
if (i>0)
{
for (j=n;j>=i+1;j--)
if (a[j]>a[i]) break ;
swap(a[i],a[j]);
sort(a+i+1,a+n+1);
for (i=1;i<=n;i++)
cout<<a[i]<< ' ' ;
cout<<endl;
}
}
return 0;
}

  这道题,还有种直接使用函数来实现的。。

转载于:https://my.oschina.net/tdd/blog/338607

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值