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>
第二种:我用的是暴力解法,就是太消耗时间了。
|
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;
}
|