ZOJ-3414-Trail Walk_计算几何

本文探讨了在代码实现中优化技巧与计算几何原理的结合,通过实例展示如何解决复杂路径分割问题,强调了避免使用斜率计算带来的误差,并提供了一个求解方案,确保了路径均匀分布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我打代码这么狗还这么懒,以后怎么办。


题意:

给n个点的坐标(整数),以坐标系原点为起点,依次连接各个点,给出正整数m,要求添加m个CP点(check point),把折线按长度平均分开(把起点考虑为第0个和第m+1个CP点)。


Input

There are multiple test cases. The first line of each case contains two integer nm(1 <= nm <= 1000). Then n pairs of integer followed, giving the coordinate of pi.

Output

The first line of each case, output "Route case_number", Then m lines followed, the ith line contains "CPcase_num: (xiyi)" where (xiyi) represent the coordinate of the CPi. Always keep three number after the decimal point.

Sample Input
3 3
1 1
2 3
3 5
Sample Output
Route 1
CP1: (1.026, 1.051)
CP2: (1.684, 2.368)
CP3: (2.342, 3.684)


计算几何里应该不难的题吧,但是由于我计算几何就是狗,而且有点新感悟就写一下。

大体过程只要按正常想法就能模拟出来,关键是公式,计算几何不要直接使用斜率的数值,但是可以通过把k写成(y1-y2)/(x1-x2)的形式表达出来,然后推出最后的式子以后再代数,这样就不会有使用斜率数值的误差了。


代码如下

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
#define mxn 1010
int n,m;
double len;
bool dcmp(double a,double b){
	return fabs(a-b)<0.001;
}
struct point{
	double x,y;
	point(double _x,double _y){x=_x,y=_y;}
	point(){};
}p[mxn];
struct ret{
	int p_id;
	double usd;
	ret(int a,double b){p_id=a,usd=b;}
};
double dist(point a,point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double deltaX(int in,double l){
	return l*(p[in+1].x-p[in].x)/sqrt((p[in+1].y-p[in].y)*(p[in+1].y-p[in].y)+(p[in+1].x-p[in].x)*(p[in+1].x-p[in].x));
}
double deltaY(int in,double l){
	return l*(p[in+1].y-p[in].y)/sqrt((p[in+1].y-p[in].y)*(p[in+1].y-p[in].y)+(p[in+1].x-p[in].x)*(p[in+1].x-p[in].x));
}
ret find(ret in,double tgt,int cp_id){
	double tem=dist(p[in.p_id],p[in.p_id+1]);
	if(tem-in.usd<=tgt||dcmp(tem-in.usd,tgt))
		return find(ret(in.p_id+1,0.0),tgt-tem+in.usd,cp_id);
	printf("CP%d: ",cp_id);
	double delta_x=deltaX(in.p_id,tgt+in.usd);
	double delta_y=deltaY(in.p_id,tgt+in.usd);
	printf("(%.3lf, %.3lf)\n",p[in.p_id].x+delta_x,p[in.p_id].y+delta_y);
	return ret(in.p_id,in.usd+tgt);
}
int main(){
	int cs=1;
	while(scanf("%d%d",&n,&m)!=EOF){
		double sum=0;
		p[0]=point(0.0,0.0);
		for(int i=1;i<=n;++i){
			scanf("%lf%lf",&p[i].x,&p[i].y);
			sum+=dist(p[i-1],p[i]);
		}
		len=sum/(m+1);
		ret start(0,0.0);
		printf("Route %d\n",cs++);
		for(int i=0;i<m;++i){
			ret tem=find(start,len,i+1);
			start=tem;
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值