2010-06-07
GCJ 2010 Round 2 : D. Grazing Google Goats
長らくハマってしまい敗退の原因となった問題D。
比較的容易と思って飛びついたD-smallでしたが、結果が合わないのは精度の問題でした。long doubleで解決するような話。
教訓
浮動小数点数の精度とかたまには考えたほうがいいよ。long doubleかわいいよlong double
- 1位のbmerryのコード(AC)をダウンロードしてsmallのデータを食わせてみたら自分のと随分違う値が出てる
- あー。これってもしかしてdoubleの計算誤差かー!!!
- double変数をlong doubleに置き換える。
- sin→sinl,cos→cosl,hypot→hypotlなど
- で、とりあえずsmallはAC
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <cstdio>
#include <cmath>
#include <cctype>
using namespace std;
#define sz(a) int((a).size())
#define pb push_back
#define rep(var,n) for(int var=0,lim=(n);var<lim;var++)
typedef long double ldouble;
typedef pair<ldouble,ldouble> dd;
int N,M;
vector<dd> p,q;
ldouble hypot(dd x1, dd x2){
return hypotl(x1.first-x2.first, x1.second-x2.second);
}
ldouble yogen(ldouble a,ldouble b,ldouble c){
return acosl((a*a+b*b-c*c)/(a*b*2));
}
ldouble ougi(ldouble r,ldouble th=M_PI*2){
return th*r*r/2;
}
ldouble deg(ldouble rad){
return 180.0*rad/M_PI;
}
ldouble area2(int m){
dd qm = q[m];
dd p0=p[0], p1=p[1];
ldouble r0=hypot(p0,qm), r1=hypot(p1,qm), d=hypot(p0,p1);
if(r0<r1) { swap(r0,r1); swap(p0,p1); } // r0 > r1に揃える
ldouble theta=yogen(r0,r1,d);
ldouble th0=yogen(r0,d,r1), th1=yogen(r1,d,r0);
ldouble h=r0*sinl(th0);
if (r0+r1==d) {
return 0; // midpoint
//} else if (th1 <= M_PI/4) {
// return ougi(r0,2*th0) + ougi(r1,2*th1) - d*h;
} else if (r0<r1+d) {
return ougi(r0,2*th0) + ougi(r1,2*th1) - d*h;
} else {
return ougi(r1);
}
return m;
}
int main(){
int T;cin>>T; // S:1-100 L:1-10
rep(t,T){
p.clear(); q.clear();
cin>>N>>M;
rep(n,N){ double x,y; cin>>x>>y; p.pb( dd(x,y) ); } // S:2 L:2-5000
rep(m,M){ double x,y; cin>>x>>y; q.pb( dd(x,y) ); } // S:1-10 L:1-1000
printf("Case #%d:", 1+t);
rep(m,M) printf(" %.9Lf", area2(m));
printf("¥n");
}
return 0;
}
コメント
トラックバック - https://topcoder-g-hatena-ne-jp.jag-icpc.org/n4_t/20100607