题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4355
题目大意:
有n个精灵,精灵的坐标x和体重w已知。
现在这n个精灵要到一个地方去集合,但是精灵不喜欢走路,有一个公式可以算出他们的不开心值的大小:
S3*W,S代表的是精灵走的路程的大小,w代表的是精灵的体重。
现在要求找到一个点,使得所有精灵到这个地方的不开心值之和最小,输出这个最小值。
解题思路:
由于函数是S3*W,该函数是3次方的,凹函数。很容易想到三分。
后来在网上看到了0.618法,试过之后发现比前者速度更快。
三分源代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#define INF 0x3f3f3f3f
#define N 50001
using namespace std;
int n;
struct node
{
double w,x;
}s[N];
bool cmp(node a,node b)
{
return a.x<b.x;
}
double total(double x)
{
int i;
double sum,temp;
sum=0;
for(i=0;i<n;i++)
{
temp=fabs(x-s[i].x);
sum+=temp*temp*temp*s[i].w;
}
return sum;
}
int main()
{
//freopen("in.txt","r",stdin);
int cs,i,count;
double r,l,rr,ll;
scanf("%d",&cs);
count=1;
while(cs--)
{
scanf("%d",&n);
memset(s,0,sizeof(s));
for(i=0;i<n;i++)
{
scanf("%lf%lf",&s[i].x,&s[i].w);
}
sort(s,s+n,cmp);
l=s[0].x;
r=s[n-1].x;
while(r-l>0.0002)
{
ll=(l*2+r)/3;
rr=(l+r*2)/3;
if(total(ll)>total(rr))
{
l=ll;
}
else
{
r=rr;
}
}
printf("Case #%d: %.0lf\n",count++,total(l));
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#define INF 0x3f3f3f3f
#define N 50001
using namespace std;
int n;
struct node
{
double w,x;
}s[N];
bool cmp(node a,node b)
{
return a.x<b.x;
}
double total(double x)
{
int i;
double sum,temp;
sum=0;
for(i=0;i<n;i++)
{
temp=fabs(x-s[i].x);
sum+=temp*temp*temp*s[i].w;
}
return sum;
}
int main()
{
//freopen("in.txt","r",stdin);
int cs,i,count;
double r,l,rr,ll;
scanf("%d",&cs);
count=1;
while(cs--)
{
scanf("%d",&n);
memset(s,0,sizeof(s));
for(i=0;i<n;i++)
{
scanf("%lf%lf",&s[i].x,&s[i].w);
}
sort(s,s+n,cmp);
l=s[0].x;
r=s[n-1].x;
while(r-l>0.0002)
{
ll=l+(r-l)*0.382;
rr=l+(r-l)*0.618;
if(total(ll)>total(rr))
{
l=ll;
}
else
{
r=rr;
}
}
printf("Case #%d: %.0lf\n",count++,total(l));
}
return 0;
}