断断续续终于刷完了计算几何专题,感觉太麻烦,小错误不断,尤其是精度问题。还有输出问题,有时候printf比cout要方便。
UVaOJ 10250
给出正方形的一组对角坐标,求另外两个坐标,用三角函数推到公式。
不妨设两点为A(x1, y1), C(x2, y2),则中点为G((x1 + x2) / 2, (y1 + y2) / 2),对角线长度为L = sqrt((x1 - x2)^2 - (y1-y2)^2)。
设直线AC与x轴的夹角为α,则sinα = (y2 - y1) / L,cosα = (x2 - x1) / L。
则另外两个坐标分别为B(Gx - L * sinα / 2, Gy + L * cosα / 2),D(Gx + L * sinα / 2, Gy - L * cosα / 2)。
#include <iostream> #include <iomanip> #include <math.h> using namespace std; struct Point { double x, y; }; int main() { Point a, b; while(cin >> a.x >> a.y >> b.x >> b.y) { Point c, d; double l = hypot(a.x - b.x, a.y - b.y); double sin = (a.y - b.y) / l; double cos = (a.x - b.x) / l; double x = (a.x + b.x) / 2.0; double y = (a.y + b.y) / 2.0; c.x = x - l * sin * 0.5; c.y = y + l * cos * 0.5; d.x = x + l * sin * 0.5; d.y = y - l * cos * 0.5; cout << fixed << setprecision(10) << c.x << " " << c.y << " " << d.x << " " << d.y << endl; } return 0; }
UVaOJ 579
时钟每小时走30°,分钟每分钟走6°,模拟即可。
#include <stdio.h> #include <stdlib.h> using namespace std; int main() { int h, m; while(scanf("%d:%d", &h, &m) != EOF) { if(h == 0 && m == 0) { break; } if(h == 12) { h = 0; } double dAngle = (h * 30.0 + m / 2.0) - m * 6.0; if(dAngle < 0) { dAngle = -dAngle; } if(dAngle > 180) { dAngle = 360 - dAngle; } printf("%.3f\n", dAngle); } return 0; }
UVaOJ 375
等腰三角形内接圆直到半径小于1E-6,根据几何关系推得半径r = tan(arctan(2 * Height / Width) / 2) * Width / 2。
#include <stdio.h> #include <math.h> using namespace std; const double PI = 4.0 * atan(1.0); int main() { int T; double x, y; scanf("%d", &T); for(int i = 1; i <= T; i++) { scanf("%lf%lf", &x, &y); double dSum = 0; double r = tan(atan(y / x * 2) / 2) * x / 2; while(r >= 1E-6) { dSum += r; x = x / y * (y - 2 * r); y -= 2 * r; r = tan(atan(y / x * 2) / 2) * x / 2; } printf("%13.6lf\n", 2 * PI * dSum); if(i != T) { printf("\n"); } } return 0; }
UVaOJ 10387
根据几何关系,速度v = L / t,角度为arctan(y / x) * 180 / PI。
#include <iostream> #include <iomanip> #include <math.h> using namespace std; int main() { double PI = acos(-1.0); double a, b, s, m, n; while(cin >> a >> b >> s >> m >> n) { if(a == 0 && b == 0 && s == 0 && m == 0 && n == 0) { break; } double x = a * m, y = b * n; double l = hypot(x, y); cout << fixed << setprecision(2) << atan(y / x) * 180.0 / PI << " " << l / s << endl; } return 0; }
UVaOJ 10112
枚举各个点,判断是否满足条件,求三角形面积可以使用三阶行列式,判断点是否在三角形内可以使用S△ABC=S△ABD+S△ACD+S△BCD来判断。
#include <iostream> #include <string> #include <math.h> using namespace std; const int MAX = 128; struct Tri { char dwLabel; int x, y; }; Tri pTri[MAX]; double fabs(double x); double Area(int i, int j, int k); bool Check(int i, int j, int k, int nPos); string Solve(int N); int main() { int N; while(1) { cin >> N; if(N == 0) { break; } cin.ignore(); for(int i = 1; i <= N; i++) { cin >> pTri[i].dwLabel >> pTri[i].x >> pTri[i].y; cin.ignore(); } cout << Solve(N) << endl; } return 0; } string Solve(int N) { double dMax = 0; string strAns = "000"; for(int i = 1; i <= N; i++) { for(int j = 1; j <= N; j++) { if(i == j) { continue; } for(int k = 1; k <= N; k++) { if(k == i || k == j) { continue; } int nPos; for(nPos = 1; nPos <= N; nPos++) { if(nPos == i || nPos == j || nPos == k) { continue; } if(Check(i, j, k, nPos)) { break; } } if(nPos == N + 1 && Area(i, j, k) > dMax) { dMax = Area(i, j, k); strAns[0] = pTri[i].dwLabel; strAns[1] = pTri[j].dwLabel; strAns[2] = pTri[k].dwLabel; } } } } return strAns; } double Area(int i, int j, int k) { return fabs(0.5 * ((pTri[k].y - pTri[i].y) * (pTri[j].x - pTri[i].x) - (pTri[j].y - pTri[i].y) * (pTri[k].x - pTri[i].x))); } bool Check(int i, int j, int k, int nPos) { double dSum = Area(i, j, nPos) + Area(i, k, nPos) + Area(j, k, nPos); double dGap = dSum - Area(i, j, k); return (fabs(dGap) < 1E-8); }
终于把小白书第一部分的推荐题目刷完了,总计65道。
时间: 2024-12-28 14:11:32