【ACM算法】Rolling The Polygon

分析:

首先这是一个数学题,要求推导出凸多边形在水平面上滚其内部某个点移动的距离的数学公式。

通过分析上面的这个例子:一开始以B为圆心QB为半径,转90度;后以C为圆心QC为半径,转90度;往后同理。最后一定转了360度。通过分析这个例子可以看出凸多边形的滚动分别以其的每个点为圆心,以这个点到Q距离作为半径,每次移动的弧度为这个点所在∠的补∠。

弧长的计算公式为: 弧长 = 弧度 * 半径

cosA=(b^2+c^2-a^2)/2bc 弧度可以通过arccos求出

代码实例(原创):

#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;
//代表每个点
typedef struct Point {
	int xi;
	int yi;
	double angle; //每个∠的补∠的弧度
	double len; //每个点到Q的距离
}Point;
//计算距离的公式
double getLen(Point x, Point y) {
	return sqrt((x.xi-y.xi) * (x.xi-y.xi) + (x.yi-y.yi) * (x.yi-y.yi));
}
class A {
	public :
		int n;
		Point x[50];
		Point Q;
	public:
		A() {
			cin >> n;
			for(int i = 0 ; i < n ; i++) {
				cin >> this->x[i].xi >> this->x[i].yi;
				//cout << this->x[i].xi << this->x[i].yi;
			}
			cin >> this->Q.xi >> this->Q.yi;
			
	//		生成每个点的角度 
			for(int i = 0 ; i < n ; i++) {
				this->x[i].len = sqrt((x[i].xi-Q.xi) * (x[i].xi-Q.xi) + (x[i].yi-Q.yi) * (x[i].yi-Q.yi));
				double a = getLen(this->x[(i + n - 1) % n], this->x[(i + 1) % n]); 
				double b = getLen(this->x[(i + n - 1) % n], this->x[i]); 
				double c = getLen(this->x[(i + 1) % n], this->x[i]); 
	//			cout << a << endl; cout << b <<endl; cout << c << endl;
				this->x[i].angle =3.1415926535 - acos((b*b + c*c - a*a) / (2 * b * c));
				cout << this->x[i].angle << endl;
	//			cout << endl;			
			}  
		}
		
		void solve() {
			int nn = this->n;
			double end = 0.0;
			for(int i = 0 ; i < nn ; i++) {
				end += this->x[i].angle * this->x[i].len; 
			}
			cout <<fixed <<setprecision(3) << end << endl; //保留三位有效数字
		}
};

int main() {
	int T;
	cin >> T;
	int i = 1;
	while(T--) {
		A a;
		cout << "Case #" << i++ << ": ";
		a.solve();
	}
	return 0;
}

补充内容cmath标准库函数

cmath中常用库函数:

int abs(int i);//返回整型参数i的绝对值
double fabs(double x);//返回双精度参数x的绝对值
long labs(long n);//返回长整型参数n的绝对值


double exp(double x);//返回指数函数e^x的值
double log(double x);//返回logex的值
double log10(double x) 返回log10x的值
double pow(double x,double y) 返回x^y的值
double pow10(int p) 返回10^p的值


double sqrt(double x) 返回+√x的值


double acos(double x) 返回x的反余弦arccos(x)值,x为弧度
double asin(double x) 返回x的反正弦arcsin(x)值,x为弧度
double atan(double x) 返回x的反正切arctan(x)值,x为弧度
double cos(double x) 返回x的余弦cos(x)值,x为弧度
double sin(double x) 返回x的正弦sin(x)值,x为弧度
double tan(double x) 返回x的正切tan(x)值,x为弧度


double hypot(double x,double y) 返回直角三角形斜边的长度(z),
  x和y为直角边的长度,z^2=x^2+y^2


double ceil(double x) 返回不小于x的最小整数
double floor(double x) 返回不大于x的最大整数


int rand() 产生一个随机数并返回这个数


double atof(char *nptr) 将字符串nptr转换成浮点数并返回这个浮点数
double atol(char *nptr) 将字符串nptr转换成长整数并返回这个整数
double atof(char *nptr) 将字符串nptr转换成双精度数,并返回这个数,错误返回0
int atoi(char *nptr) 将字符串nptr转换成整型数, 并返回这个数,错误返回0
long atol(char *nptr) 将字符串nptr转换成长整型数,并返回这个数,错误返回0
摘自:http://blog.sina.com.cn/s/blog_68e462650100l3zy.html

保留有效数字的方法

#include <iomanip> 头文件

cout <<fixed <<setprecision(3) << end << endl; //保留三位有效数字

cout << setiosflags(ios::fixed) <<setprecision(3) << n << endl; //控制保留三位小数,不够0填

补充

调试的时候发现输出了NaN 这个表示not a number 一般是因为对负数开方,对负数求对数,0.0/0.0,0.0*inf、inf/inf、inf-inf这些操作都会得到nan。(0/0会产生操作异常;0.0/0.0不会产生操作异常,而是会得到nan)或者次类型为非数值类型。

猜你喜欢

转载自blog.csdn.net/qq_37406764/article/details/81125657
今日推荐