寒假练习 07

断断续续终于刷完了计算几何专题,感觉太麻烦,小错误不断,尤其是精度问题。还有输出问题,有时候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道。

posted @ 2015-02-17 11:37  Ivy_End  阅读(171)  评论(0编辑  收藏  举报