思路:分析完这道题后会发现 当两个人捡到第一个瓶子后, 之后走的路的最小值都是不会变的了。 所以只要找出两个走到各自的第一个瓶子是最小值的情况的时候(其中还有一个人不走,一个人走的情况)。 如果当有两个人或有一个人到其第一个瓶子的权值大于瓶子到回收点时,选取权值小的那个。
而且计算最小值的时候 只需取出两个权值数组中最小的两个数 即可 不用全部遍历来选取。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; double a[100100],b[100100],t[100100]; double minn[4],sum,chang; int under[4]; double distance(double x,double y,double x1,double y1){ return sqrt(pow((x-x1)*1.0,2)+pow((y-y1)*1.0,2)+0.0); } int main(){ //int ax,ay,bx,by,tx,ty,n,tempx,tempy; int n; double ax,ay,bx,by,tx,ty,tempx,tempy; scanf("%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&tx,&ty); scanf("%d",&n); sum=0; for(int i=1;i<=n;i++){ scanf("%lf%lf",&tempx,&tempy); t[i] = distance(tx,ty,tempx,tempy); sum += 2*t[i]; a[i] = distance(ax,ay,tempx,tempy) - t[i]; b[i] = distance(bx,by,tempx,tempy) - t[i]; //cout<<a[i]<<" "<<b[i]<<endl; } minn[0] = a[1];under[0] = 1; minn[2] = b[1];under[2] = 1; //找出a[i]数组的两个最小值 for(int i=1;i<=n;i++){ if(a[i]<minn[0]){ minn[0] = a[i]; under[0] = i; } } for(int i=1;i<=n;i++) if(i!=under[0]) minn[1] = a[i],under[1] = i; for(int i=1;i<=n;i++){ if(i!=under[0]&&a[i]<minn[1]){ minn[1] = a[i]; under[1] = i; } } //找出b[i]数组的两个最小值 for(int i=1;i<=n;i++){ if(b[i]<minn[2]){ minn[2] = b[i]; under[2] = i; } } for(int i=1;i<=n;i++) if(i!=under[2]) minn[3] = b[i],under[3] = i; for(int i=1;i<=n;i++){ if(i!=under[2]&&b[i]<minn[3]){ minn[3] = b[i]; under[3] = i; } } // 当n=1的时候会有就没有两个最小值了 所以要当成特殊情况? if(n==1) chang = min(a[1],b[1]); else if(under[0]!=under[2]){ chang = min(min(minn[0]+minn[2],minn[0]),minn[2]); }else{ chang = min(min(min(minn[0]+minn[3],minn[1]+minn[2]),minn[0]),minn[2]); } printf("%.12lf\n",sum+chang); return 0; }