CodeChef submission 20886 (C++ 4.0.0-8) plaintext list. Status: AC, problem BX, contest APRIL09. By anshuman_singh (Anshuman Singh), 2009-04-15 14:44:31.
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iterator> #include<map> #include<vector> #include<list> #include<set> #include<queue> #include<cassert> #include<deque> #include<stack> #include<numeric> #include<sstream> #include<string> #include<cmath> using namespace std; #define LET(x,a) __typeof(a) x(a) #define IFOR(i,a,b) for(LET(i,a);i!=(b);++i) #define EACH(it,v) IFOR(it,v.begin(),v.end()) #define FOR(i,a,b) for(int i=(int)(a) ; i < (int)(b);++i) #define REP(i,n) FOR(i,0,n) #define SZ size() #define PB push_back #define EPS 1e-9 #define D_EQ(a,b) (a>b-EPS && a<b+EPS) #define D_LT(a,b) ((a)<((b)-EPS)) #define D_LTEQ(a,b) ((a)<((b)+EPS)) #define D_GT(a,b) ((a)>((b)+EPS)) #define D_GTEQ(a,b) ((a)>((b)-EPS)) #define ABS(a) ((a)>=0?(a):(-1.0*(a))) #define V(x) vector< x > #define INF 100000000 #define SQ(a) ((a)*(a)) typedef vector<int> VI; typedef long long LL; typedef pair<int,int> PI; double x[2000],y[2000],dist[2000]; int n,connectedTo[2000],edgeCnt; bool done[2000]; PI TreeEdges[10000],tempEdges[10000]; /* Basic definitions of point class and line class */ struct Vector { double x, y; inline Vector operator-(const Vector &v) const{ return Vector(x-v.x, y-v.y); } inline Vector operator+(const Vector &v) const{ return Vector(x+v.x, y+v.y); } inline Vector operator/(double fact) const{ return Vector(x/fact, y/fact); } inline Vector operator*(double fact) const{ return Vector(x*fact, y*fact); } inline bool operator==(const Vector &v) const{ } inline bool operator<(const Vector &v)const{ if(D_EQ(x,v.x)){ return (D_LT(y,v.y)); } return D_LT(x,v.x); } inline Vector(){}; inline Vector(double x, double y):x(x),y(y){}; }; typedef Vector Point; struct Segment{ Point c1,c2; inline bool operator==(const Segment &s) const {return c1==s.c1 && c2==s.c2;} inline Segment(){}; inline Segment(const Point &c1, const Point &c2) : c1(c1), c2(c2) {}; }; struct Line{ Point c1, c2; inline bool operator==(const Line &l) const {return c1==l.c1 && c2==l.c2;} inline Line(){}; inline Line(const Point &c1, const Point &c2) : c1(c1), c2(c2) {}; inline Line(const Segment &s):c1(s.c1),c2(s.c2){}; }; inline double lensqr(const Vector &v){ return v.x*v.x + v.y*v.y; } inline double len(const Vector &v){ } inline double dotp(const Vector &v1, const Vector &v2){ return v1.x*v2.x + v1.y*v2.y; } inline double crossp(const Vector &v1, const Vector &v2){ return v1.x*v2.y - v1.y*v2.x; } inline double dotp(const Line &l, const Point &p){ return dotp(l.c2-l.c1, p-l.c1); } inline double crossp(const Line &l, const Point &p){ return crossp(l.c2-l.c1, p-l.c1); } inline double dotp(const Segment &l, const Point &p){ return dotp(l.c2-l.c1, p-l.c1); } inline double crossp(const Segment &l, const Point &p){ return crossp(l.c2-l.c1, p-l.c1); } inline double operator*(const Vector &v1,const Vector &v2){ return dotp(v1,v2); } inline double operator^(const Vector &v1,const Vector &v2){ return crossp(v1,v2); } inline double pointLineDistance(const Line &l,const Point &p){ double dist = ((l.c2-l.c1)^(p-l.c1))/len(l.c2-l.c1); } inline double pointSegmentDistance(const Segment &s,const Point &p){ double dist = ((s.c2-s.c1)^(p-s.c1))/len(s.c2-s.c1),dot1,dot2; dot1 = (p-s.c2)*(s.c2-s.c1);if(dot1 > EPS) return dot1; dot2 = (p-s.c1)*(s.c1-s.c2);if(dot2 > EPS) return dot2; } inline double area(vector<Point> &p){ double res=0.0; REP(i,p.SZ) res += p[i].x*p[(i+1)%p.SZ].y - p[(i+1)%p.SZ].x*p[i].y; } inline Point rotate(Point p,double theta){ } Point intersectionPoint( const Line &l1, const Line &l2 ){ Point ret(INF, INF); double d1 = crossp(l1, l2.c1); double d2 = crossp(l1, l2.c2); ret.x = l2.c1.x + (l2.c2.x-l2.c1.x)*d1/(d1-d2); ret.y = l2.c1.y + (l2.c2.y-l2.c1.y)*d1/(d1-d2); return ret; } Point intersectionPoint(const Segment &l1, const Segment &l2){ Point ret(INF, INF); double d1 = crossp(l1, l2.c1); double d2 = crossp(l1, l2.c2); ret.x = l2.c1.x + (l2.c2.x-l2.c1.x)*d1/(d1-d2); ret.y = l2.c1.y + (l2.c2.y-l2.c1.y)*d1/(d1-d2); if(ret.x >= (l1.c1.x<?l1.c2.x)-EPS && ret.x <= (l1.c1.x>?l1.c2.x)+EPS){ if(ret.y >= (l1.c1.y<?l1.c2.y)-EPS && ret.y <= (l1.c1.y>?l1.c2.y)+EPS){ if(ret.x >= (l2.c1.x<?l2.c2.x)-EPS && ret.x <= (l2.c1.x>?l2.c2.x)+EPS){ if(ret.y >= (l2.c1.y<?l2.c2.y)-EPS && ret.y <= (l2.c1.y>?l2.c2.y)+EPS){ return ret; } } } } return Point(INF,INF); } double highestAngle(Point p1,Point p2,Point p3){ double s[3]; s[0]=len(p1-p2),s[1]=len(p2-p3),s[2]=len(p3-p1); sort(s,s+3); REP(i,3)if(D_EQ(s[i],0))return 180; double ang = (double)acosl((s[0]*s[0]+s[1]*s[1]-s[2]*s[2])/(2.0*s[0]*s[1])); } Line GetLine(Point p1,Point p2,Point p3){ //getting the point on the equilateral triangle of p1,p2,m and forming line p3,m Line L(p1,p2); Point mid = (p1 + p2); mid.x/=2.0;mid.y/=2.0; Vector tmp = mid - p1; tmp=tmp/len(tmp); tmp = rotate(tmp,90); double SideLen = len(p1-p2); SideLen*=(sqrtl(3.0)/2.0); Point m=tmp*SideLen; m=m+mid; if(crossp(L,m)*crossp(L,p3)<0){ return Line(m,p3); } else { m=m-mid; m=mid-m; return Line(m,p3); } } Point ToricelliPoint(Point p1,Point p2,Point p3){ Line l1=GetLine(p1,p2,p3),l2=GetLine(p1,p3,p2); return intersectionPoint(l1,l2); } Point locallyOptimize(Point t,Point p1,Point p2,Point p3){ bool bettered=1; double curDist = d1+d2+d3; vector<pair<int,double> > v; REP(i,edgeCnt){ int k1=TreeEdges[i].first,k2=TreeEdges[i].second; bool poss1=0,poss2=0; Point n1(x[k1],y[k1]),n2(x[k2],y[k2]); if(n1==p1||n1==p2||n1==p3)poss1=1; if(n2==p1||n2==p2||n2==p3)poss2=1; if(!poss1 && poss2){ v.PB(make_pair(k1,l)); } else if(poss1 && !poss2)v.PB(make_pair(k2,l)); } while(bettered){ bettered=0; for(double x1=t.x-5;x1<=t.x+5;x1+=0.05){ for(double y1=t.y-5;y1<=t.y+5;y1+=0.05){ Point t1(x1,y1); double sub=0; REP(i,(int)v.size()){ Point n1(x[v[i].first],y[v[i].first]); sub+=max(0.0,v[i].second-dist); } if(d11+d12+d13-sub<curDist){ curDist=d11+d12+d13-sub; t=t1; bettered=1; } } } } return t; } int graph[1501][1501]; int main(){ //prim MST done[0]=1; REP(i,2000){ dist[i]=1e20; } REP(i,n)if(i){ dist[i]=SQ(x[i]-x[0])+SQ(y[i]-y[0]); connectedTo[i]=0; } edgeCnt=0; REP(i,n-1){ double min1=1e20; int pt=-1; REP(i,n)if(!done[i] && dist[i]<min1){ min1=dist[i]; pt=i; } done[pt]=1; TreeEdges[edgeCnt++]=make_pair(pt,connectedTo[pt]); REP(i,n)if(!done[i]){ double newDist=(SQ(x[i]-x[pt])+SQ(y[i]-y[pt])); if(newDist<dist[i]){ dist[i]=newDist; connectedTo[i]=pt; } } } int added=0,cur=n,oldEdgeCnt=edgeCnt; long double profit=0; PI TempTreeEdge[10000]; REP(i,edgeCnt)TempTreeEdge[i]=TreeEdges[i]; REP(i,edgeCnt){ graph[TreeEdges[i].first][TreeEdges[i].second]=1; graph[TreeEdges[i].second][TreeEdges[i].first]=1; } double best = 0; pair<pair<int,int>,int> bestOption; REP(i,edgeCnt+1){ if(i==edgeCnt && best>1e-7){ int index1=bestOption.first.first,index2=bestOption.first.second,j=bestOption.second; Point p3=Point(x[j],y[j]),p1=Point(x[index1],y[index1]),p2=Point(x[index2],y[index2]); if(highestAngle(p1,p2,p3)+EPS<120.0){ Point t1 = ToricelliPoint(p1,p2,p3); Point t=locallyOptimize(t1,p1,p2,p3); //try including other n-1 points in locally optimize too double d1=len(p1-p2),d2=len(p1-p3); double d3=len(p1-t),d4=len(p2-t),d5=len(p3-t); int ind = -1,ind2=-1; REP(tmp,edgeCnt){ if((j==TreeEdges[tmp].first && index1==TreeEdges[tmp].second)||(j==TreeEdges[tmp].second && index1==TreeEdges[tmp].first)){ ind=tmp; break; } } REP(tmp,edgeCnt){ if((index2==TreeEdges[tmp].first && index1==TreeEdges[tmp].second)||(index2==TreeEdges[tmp].second && index1==TreeEdges[tmp].first)){ ind2=tmp; break; } } graph[index1][index2]=0; graph[index2][index1]=0; graph[index1][j]=0; graph[j][index1]=0; graph[index1][cur]=1; graph[index2][cur]=1; graph[j][cur]=1; graph[cur][index1]=1; graph[cur][index2]=1; graph[cur][j]=1; REP(i1,edgeCnt){ int k1=TreeEdges[i1].first,k2=TreeEdges[i1].second; bool poss1=0,poss2=0; Point n1(x[k1],y[k1]),n2(x[k2],y[k2]); if(k1==index1||k1==j||k1==index2)poss1=1; if(k2==index1||k2==j||k2==index2)poss2=1; if(!poss1 && poss2){ sub=l-sub; if(sub>EPS){ graph[k1][k2]=graph[k2][k1]=0; graph[k1][cur]=graph[cur][k1]=1; TreeEdges[i1]=make_pair(k1,cur); } } else if(poss1 && !poss2){ sub=l-sub; if(sub>1e-5){ graph[k1][k2]=graph[k2][k1]=0; graph[k2][cur]=graph[cur][k2]=1; TreeEdges[i1]=make_pair(k2,cur); } } } TreeEdges[ind2]=make_pair(index1,cur); TreeEdges[ind]=make_pair(j,cur); TreeEdges[edgeCnt++]=make_pair(index2,cur); x[cur]=t.x;y[cur++]=t.y; added++; i=-1; best=0; continue; } } } int index1=TreeEdges[i].first,index2=TreeEdges[i].second; Point p1=Point(x[index1],y[index1]),p2=Point(x[index2],y[index2]); REP(j,cur)if(graph[index1][j] && j!=index1 && j!=index2){ Point p3=Point(x[j],y[j]); if(highestAngle(p1,p2,p3)+EPS<120.0){ Point t = ToricelliPoint(p1,p2,p3); double d1=len(p1-p2),d2=len(p1-p3); double d3=len(p1-t),d4=len(p2-t),d5=len(p3-t); bestOption = make_pair(make_pair(index1,index2),j); } } } REP(j,cur)if(graph[index2][j] && j!=index2 && j!=index1){ Point p3=Point(x[j],y[j]); if(highestAngle(p1,p2,p3)+EPS<120.0){ Point t = ToricelliPoint(p1,p2,p3); double d1=len(p1-p2),d2=len(p2-p3); double d3=len(p1-t),d4=len(p2-t),d5=len(p3-t); bestOption = make_pair(make_pair(index2,index1),j); } } } } long double cost1=0,cost2=0; REP(i,edgeCnt){ Point p1=Point(x[TreeEdges[i].first],y[TreeEdges[i].first]),p2=Point(x[TreeEdges[i].second],y[TreeEdges[i].second]); double d=len((p1-p2)); cost1+=d; } REP(i,oldEdgeCnt){ Point p1=Point(x[TempTreeEdge[i].first],y[TempTreeEdge[i].first]),p2=Point(x[TempTreeEdge[i].second],y[TempTreeEdge[i].second]); double d=len((p1-p2)); cost2+=d; } if(cost1<cost2){ //output the answer } else { } return 0; }
Comments

