http://codeforces.com/contest/672/problem/C
按题意,只需要某个人第一次捡了后,回到原点后,后面的操作的距离 就都是 原点到各点的距离。
所以直接预处理sum=每个点到原点T的距离
然后预处理每个点到a的距离,到b的距离
显然如果要节约时间,就看a的第一步能不能省时间, 找最大的(dis(a,i) - dis(t,i ))
b同理。
所以方案是 只选a
只选b
a,b都选
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.00000001;
int n;
struct node
{
double x,y;
int id;
double val;
int type;
};
node tt[100005];
node bb[100005];
double xx[100005];
double yy[100005];
bool cmp(node a,node b)
{
return a.val>b.val;
}
int main()
{
double ax,ay,bx,by,tx,ty;
cin>>ax>>ay>>bx>>by>>tx>>ty;
cin>>n;
double x,y;
double sum=0;
int ok=0,bok=0;;
int i,j;
double sta=sqrt((ax-tx)*(ax-tx)+(ay-ty)*(ay-ty) );
double stb=sqrt((bx-tx)*(bx-tx)+(by-ty)*(by-ty) );
for ( i=1; i<=n; i++)
{
scanf("%lf%lf",&xx[i],&yy[i]);
double dis=sqrt((xx[i]-tx)*(xx[i]-tx)+(yy[i]-ty)*(yy[i]-ty));
double disa=sqrt((xx[i]-ax)*(xx[i]-ax)+(yy[i]-ay)*(yy[i]-ay));
double disb=sqrt((xx[i]-bx)*(xx[i]-bx)+(yy[i]-by)*(yy[i]-by));
sum+=2* dis;
++ok;
tt[ok].id=i;
tt[ok].val=dis- disa; //节约time
++bok;
bb[bok].id=i;
bb[bok].val=dis- disb;
}
sort(bb+1,bb+1+bok,cmp);
sort(tt+1,tt+1+ok,cmp);
int hasreturn=0;
double ansa=sum-tt[1].val;
double ansb=sum-bb[1].val;
double ansc=1e18;
if (tt[1].id!=bb[1].id)
ansc=sum-tt[1].val-bb[1].val;
else
if (n>1)
ansc=min(sum-tt[1].val-bb[2].val
, sum-tt[2].val-bb[1].val);
printf("%.6lf\n",min(ansa,min(ansc,ansb)));
return 0;
}

本文解析了CodeForces竞赛中一道题目C的解决方案,通过预处理距离和选择最优路径来减少总行走时间,实现算法优化。
321

被折叠的 条评论
为什么被折叠?



