CGL_7_G : Common Tangent

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_7_G
2円の共通接線の接点を答える問題。
紙の上での式変形に一時間くらいかかった、、、
内積と半径を連立させる標準的な解法。
C++で最も短いコードを達成。
だから何だと言われればそれだけ。

ショートコードの技法を投入すれば1位のRubyの人に肉薄はできそうだけど、そこまでやるのはめんどいな。
私の解法はRubyの人と同じだったぽい。



関係ないが私の作った競技プログラムの問題
35人に解いてもらった。
http://yukicoder.me/problems/no/417
上手に分割すると頂点数だけナップザック問題を解けばいいシンプルな問題。
10歳から引きこもりで小卒同然の私が自力で作ったにしてはいい問題だとおもってる




#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<set>
struct E{
   double x,y;
   bool operator<(const E& e)const{
       if(x!=e.x)return x<e.x;
       return y<e.y;
   }
};

int main(){
   double x1,y1,r1,x2,y2,r2,h;
   scanf("%lf %lf %lf %lf %lf %lf",&x1,&y1,&r1,&x2,&y2,&r2);
   x2-=x1;
   y2-=y1;
   h=hypot(x2,y2);
   std::set<E> ans;
   if(std::max(r1,r2)<=h+std::min(r1,r2)){
       double r3,r4,a,b,c,xa1,xa2;
       r3=r2/r1;
       r4=r1*r1*(r3-1.0);
       a=x2*x2+y2*y2;
       b=2*r4*x2;
       c=r4*r4-y2*y2*r1*r1;
       E e1,e2;
       double d=b*b-4*a*c;
       if(d<0)d=0;
       d=sqrt(d);
       xa1=(-b+d)/(2*a);
       xa2=(-b-d)/(2*a);
       if(y2==0){
           e1.x=xa1;
           double t=r1*r1-xa1*xa1;
           if(t<0)t=0;
           t=sqrt(t);
           e1.y=t;
           ans.insert(e1);
           e2.x=xa2;
           e2.y=-t;
           ans.insert(e2);
       }else{
           e1.x=xa1;
           e1.y=(-r4-xa1*x2)/y2;
           ans.insert(e1);
           e2.x=xa2;
           e2.y=(-r4-xa2*x2)/y2;
           ans.insert(e2);
       }
        
   }
   if(r1+r2<=h){
       double r3,r4,a,b,c,d;
       E e1,e2;
       r3=r2/r1;
       r4=r1*r1*(1+r3);
       a=x2*x2+y2*y2;
       b=-2*r4*x2;
       c=r4*r4-y2*y2*r1*r1;
       d=b*b-4*a*c;
       if(d<0)d=0;
       d=sqrt(d);
       e1.x=(-b-d)/(2*a);
       e2.x=(-b+d)/(2*a);
       if(y2==0){
           double t=r1*r1-e1.x*e1.x;
           if(t<0)t=0;
           t=sqrt(t);
           e1.y=t;
           e2.y=-t;
           ans.insert(e1);
           ans.insert(e2);
       }else{
           e1.y=(r4-e1.x*x2)/y2;
           e2.y=(r4-e2.x*x2)/y2;
           ans.insert(e1);
           ans.insert(e2);
       }
   }
   std::set<E>::iterator it;
   for(it=ans.begin();it!=ans.end();it++){
       printf("%.7lf %.7lf\n",(*it).x+x1,(*it).y+y1);
   }
}
最終更新:2016年11月11日 15:25