题目链接:
http://codeforces.com/contest/672/problem/C
题意:
公园里有两个人一个垃圾桶和n个瓶子,现在这两个人需要把所有的瓶子扔进垃圾桶,给出人,垃圾桶,瓶子的坐标,问两个人需要走的最短距离和。
题解:
首先必须要有一个人先去检一个瓶子,然后走到垃圾桶,这个可以枚举,接下来就是考虑另一个人是也捡一个瓶子然后走到垃圾桶(这个可以预处理出最优的,和次优的,因为如果最优的那个刚好被第一个人拿走了,那就拿次优的)还是在原地不动,接下去就是固定的了,求剩下的所有瓶子到垃圾桶的距离的两倍就可以了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int maxn = 1e5+10; const double eps = 1e-8; typedef long long LL; struct Point { int x, y; Point(int x, int y) :x(x), y(y) {} Point() {} }pt[maxn]; inline double dis(const Point& n1, const Point& n2) { return sqrt((LL)(n1.x - n2.x)*(n1.x - n2.x) + (LL)(n1.y-n2.y)*(n1.y - n2.y)); } int ax, ay, bx, by, tx, ty,n; double cnt; struct Node { int id; double v; bool operator < (const Node& tmp)const { return v< tmp.v; } }nda[maxn],ndb[maxn]; void pre(Point aa, Point bb, const Point &bin) { for (int i = 0; i < n; i++){ nda[i].v = dis(aa, pt[i]) - dis(bin, pt[i]); nda[i].id = i; ndb[i].v = dis(bb, pt[i]) - dis(bin, pt[i]); ndb[i].id = i; } sort(nda, nda + n); sort(ndb, ndb + n); } double solve(const Node* nd,Point aa, Point bb, const Point &bin) { //这个地方写成了ret=cnt,哇在41哇了好几个小时!!!!!!!!!!!!!!! //这样如果两个人都不动会更优的话就变成输出两个人都不动的答案啦!人都没动,垃圾桶不会自己去找瓶子啊!!!! //orz orz orz double ret; for (int i = 0; i < n; i++) { double sum = cnt - dis(bin, pt[i])+dis(aa,pt[i]); if (nd[0].id != i) { sum = min(sum,sum + nd[0].v); } else { if(n>1) sum = min(sum,sum + nd[1].v); } if (i == 0) ret = sum; else ret = min(ret, sum); } return ret; } void init() { cnt = 0; } int main() { while (scanf("%d%d%d%d%d%d", &ax, &ay, &bx, &by, &tx, &ty) == 6) { init(); scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d%d", &pt[i].x, &pt[i].y); cnt += dis(pt[i], Point(tx, ty))*2; } pre(Point(ax, ay), Point(bx, by), Point(tx, ty)); double ans; ans=solve(ndb,Point(ax, ay), Point(bx, by), Point(tx, ty)); ans=min(ans,solve(nda,Point(bx, by),Point(ax, ay), Point(tx, ty))); printf("%.12lf ", ans); } return 0; } /* 1 0 0 1 0 0 2 1 1 2 2 */