买一赠二啊。。。。T T 。。。poj这两题居然完全一样,就输入方式不一样,情何以堪!什么质量啊。。
给你最后一排球的坐标,求最顶层的球的坐标。
我直接一排一排模拟的,无奈用的三角函数,精度死活达不到,WA死了。。。搜题解,学到一个向量旋转的方法,http://dumbear.com/blog/?p=143 可以看下这个。总之呢,能不用精度的就不要用了。
还有一种方法就是,因为题目已经告诉你了,最顶的球的x坐标一定是最左和最右球坐标的中点,http://fghtech.blogbus.com/logs/56860901.html,这个做法,好聪明,直接推算出来y坐标。
这道题就学到了,精度是个很纠结的东西。。。以后能不用三角函数就不用。
#include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <string.h> #include <algorithm> using namespace std; const int MAX = 15; const double eps = 1e-6; bool xy(double x,double y) { return x < y - eps;} // x < y struct point{ double x,y;}; point p[MAX]; point t[MAX]; int n; double disp2p(point a,point b) { return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); } point intersection(point u1,point u2,point v1,point v2) { point ans = u1; double t = ((u1.x - v1.x)*(v1.y - v2.y) - (u1.y - v1.y)*(v1.x - v2.x))/ ((u1.x - u2.x)*(v1.y - v2.y) - (u1.y - u2.y)*(v1.x - v2.x)); ans.x += (u2.x - u1.x)*t; ans.y += (u2.y - u1.y)*t; return ans; } point Whirl(double cosl, double sinl, point a, point b) { b.x -= a.x; b.y -= a.y; point c; c.x = b.x * cosl - b.y * sinl + a.x; c.y = b.x * sinl + b.y * cosl + a.y; return c; } point find(point a,point b) { double d = disp2p(a,b); double cosl = d / 4.0; double sinl = sqrt(1.0 - cosl*cosl); point a1, b1; b1 = Whirl(cosl,sinl,a,b); //底边线段ab 绕a旋转b->b1 a1 = Whirl(cosl,-sinl,b,a); //底边线段ab绕b选择a->a1 return intersection(a,b1,a1,b); } bool cmp(point a,point b) { return xy(a.x,b.x); } int main() { while( ~scanf("%d",&n) && n ) { for(int i=0; i<n; i++) { scanf("%lf",&p[i].x); p[i].y = 1.0; } sort(p,p+n,cmp); memcpy(t,p,sizeof(p)); for(int k=n-1; k>=1; k--) { for(int i=1; i<=k; i++) t[i-1] = find(p[i-1],p[i]); for(int i=0; i<k; i++) p[i] = t[i]; } printf("%.4lf %.4lf/n",t[0].x,t[0].y); } return 0; }