计算几何第一章--点线面形,点积叉积(POJ2318+POJ2398+POJ3304+POJ1296)(未完待续


A: POJ 2318 TOYS

题意:给一个矩形,给出多个木板的位置(线段),将矩形分割成了多个格子(不一定规则),给出多个toy的位置(抽象成点了),判断每个玩具在第几个格子里。

思路:由于给出的木板是不相交,而且严格从左到右的,所以二分查找toy掉落的位置。判断在哪个区间用叉积判断即可。

代码:

#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
struct Point{
	int x,y;
}toys[5005];
struct V{
	Point a,b;
}bin[5005];
double crossProduct(V v1,V v2){
	double ans = 0;
	ans = (v1.b.x-v1.a.x)*(v2.b.y-v2.a.y) - (v1.b.y-v1.a.y)*(v2.b.x-v2.a.x);
	return ans;
}
int num[5005],n,m;
int bin_search(Point x){
	int l = 0,r = n-1,mid = 0;
	V v1;
	v1.a = bin[0].a;	v1.b = x;
	if(crossProduct(v1,bin[0]) < 0)return 0;
	v1.a = bin[n-1].a;	v1.b = x;
	if(crossProduct(v1,bin[n-1]) > 0)return n;
	mid = (l+r)/2;
	while(l < r){
		v1.a = bin[mid].a;
		if(crossProduct(v1,bin[mid]) > 0)l = mid+1;
		else r = mid;
		mid = (l+r)/2;
	}
	return mid;
}
int main(){
	int x1,y1,x2,y2,xx1,xx2,x,y;
	while(cin>>n,n){
		cin>>m>>x1>>y1>>x2>>y2;
		for (int i = 0; i < n; i++)
		{
			cin>>xx1>>xx2;
			bin[i].b.x = xx1;bin[i].b.y = y1;
			bin[i].a.x = xx2;bin[i].a.y = y2;
		}
		memset(num,0,sizeof(num));
		Point t;
		for (int j = 0; j < m; j++)
		{
			cin>>x>>y;
			t.x = x;
			t.y = y;
			num[bin_search(t)]++;
		}
		for (int i = 0; i <= n; i++)
		{
			printf("%d: %d\n",i,num[i]);
		}
		printf("\n");
	}
	return 0;
}

B: POJ 2398  Toy Storage

题意:和上题一样,只是木板的放置位置并没有严格排序,要求输出的结果是x: y,表示一共有y块里面有x个玩具的模块。输出按x的升序输出。

思路:将木板排序后,同上题。

代码:

#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
struct Point{
	int x,y;
}toys[5005];
struct V{
	Point a,b;
}bin[5005];
double crossProduct(V v1,V v2){
	double ans = 0;
	ans = (v1.b.x-v1.a.x)*(v2.b.y-v2.a.y) - (v1.b.y-v1.a.y)*(v2.b.x-v2.a.x);
	return ans;
}
int num[5005],n,m;
int bin_search(Point x){
	int l = 0,r = n-1,mid = 0;
	V v1;
	v1.a = bin[0].a;	v1.b = x;
	if(crossProduct(v1,bin[0]) < 0)return 0;
	v1.a = bin[n-1].a;	v1.b = x;
	if(crossProduct(v1,bin[n-1]) > 0)return n;
	mid = (l+r)/2;
	while(l < r){
		v1.a = bin[mid].a;
		if(crossProduct(v1,bin[mid]) > 0)l = mid+1;
		else r = mid;
		mid = (l+r)/2;
	}
	return mid;
}
int cmp(V a,V b){
	return a.a.x < b.a.x;
}
int main(){
	int x1,y1,x2,y2,xx1,xx2,x,y;
	while(cin>>n,n){
		cin>>m>>x1>>y1>>x2>>y2;
		for (int i = 0; i < n; i++)
		{
			cin>>xx1>>xx2;
			bin[i].b.x = xx1;bin[i].b.y = y1;
			bin[i].a.x = xx2;bin[i].a.y = y2;
		}
		sort(bin,bin+n,cmp);
		memset(num,0,sizeof(num));
		Point t;
		for (int j = 0; j < m; j++)
		{
			cin>>x>>y;
			t.x = x;
			t.y = y;
			num[bin_search(t)]++;
		}
				int num2[1005];
		memset(num2,0,sizeof(num2));
		for (int i = 0; i <= n; i++)
		{
			if(num[i] != 0)num2[num[i]]++;
		}
		printf("Box\n");
		for (int i = 1; i <= m; i++)
		{
			if(num2[i] != 0){
				printf("%d: %d\n",i,num2[i]);
			}
		}
	}
	return 0;
}


C: POJ 3304  Segments

题意:给出n条线段,问能否找一个角度,使所有线段以该角度投影到一条直线上,使得所有的线段的投影都有公共点。

思路:将原题题意 理解 变换为 能否找到一条直线 与所有线段都有交点。数据大小只有100,随意枚举O(n^3)完全可以。

注意:用两点确定一条直线时,保证这两点不相等。判断直线和线段的交点,用线段两端点和直线上两点做两次叉积求乘积,为负即为相交。

代码:

#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define eps 1e-8
struct Point{
	double x,y;
}toys[5005];
struct V{
	Point a,b;
}bin[5005];
struct Seg{
	Point a,b;
}s[110];
int n;
double crossProduct(V v1,V v2){//v1 X v2
	double ans = 0;
	ans = (v1.b.x-v1.a.x)*(v2.b.y-v2.a.y) - (v1.b.y-v1.a.y)*(v2.b.x-v2.a.x);
	return ans;
}
double cross(Point a,Point b,Point c){//b->a X b->c
	return (a.x-b.x)*(c.y-b.y)-(c.x-b.x)*(a.y-b.y);
}
bool ok(Point a,Point b){
	if(fabs(a.x-b.x)<eps && fabs(a.y-b.y)<eps)return 0;
	for (int i = 0; i < n; i++)
	{
		if(cross(a,s[i].a,b) * cross(a,s[i].b,b) > 0)
			return false;
	}
	return true;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for (int i = 0; i < n; i++)
			scanf("%lf%lf%lf%lf",&s[i].a.x,&s[i].a.y,&s[i].b.x,&s[i].b.y);
		if(n == 1){puts("Yes!");continue;};
		bool flag = false;
		for (int i = 0; i < n && !flag; i++)
			for (int j = i+1; j < n && !flag; j++){
				if(ok(s[i].a,s[j].a)||ok(s[i].a,s[j].b)||ok(s[i].b,s[j].a)||ok(s[i].b,s[j].b))
					flag = true;
			}
		puts(flag?"Yes!":"No!");
	}
	return 0;
}

D:POJ 1296 Intersecting Lines

题意:判断两条直线的关系:平行,重合,交于一点(输出交点)

思路:叉积判断是否平行或重合,否则数学方法求直线交点。

注意:G++用%.2lf会WA,换c++就好了。(只限POJ)

代码:

#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define eps 1e-6
struct Point{double x,y;};
struct Line{Point a,b;};
double cross(Point a,Point b,Point c){//b->a X b->c
	return (a.x-b.x)*(c.y-b.y)-(c.x-b.x)*(a.y-b.y);
}
double crossProduct(Line v1,Line v2){  
    return (v1.b.x-v1.a.x)*(v2.b.y-v2.a.y) - (v1.b.y-v1.a.y)*(v2.b.x-v2.a.x);  
}  
inline bool equal(double x,double y){
	if(fabs(x-y)<eps)return true;
	return false;
}
int n;
int main(){
	while(~scanf("%d",&n)){
		printf("INTERSECTING LINES OUTPUT\n");
		Line l1,l2;
		while(n--){
			scanf("%lf%lf%lf%lf",&l1.a.x,&l1.a.y,&l1.b.x,&l1.b.y);
			scanf("%lf%lf%lf%lf",&l2.a.x,&l2.a.y,&l2.b.x,&l2.b.y);
			if(fabs(crossProduct(l1,l2)) < eps){
				Line l3;	l3.a = l1.a; 
				/*新建一条直线(从l1的一点指向l2的一点)用于判断两直线是否重合。*/
				/*但需要注意选的两个点不能重合。。。*/
				if(equal(l1.a.x,l2.b.x) && equal(l1.a.y,l2.b.y))l3.b = l2.a;
				else l3.b = l2.b;
				if(fabs(crossProduct(l1,l3)) < eps)
					puts("LINE");
				else puts("NONE");
			}else{
				Point ans;
				bool c1 = equal(l1.a.x,l1.b.x),c2 = equal(l2.a.x,l2.b.x);
				double k1,k2,b1,b2;
				if(c1 && !c2){
					k2 = (l2.b.y-l2.a.y)/(l2.b.x-l2.a.x);
					b2 = l2.b.y-k2*l2.b.x;
					ans.x = l1.a.x;
					ans.y = k2*ans.x+b2;
				}else if(!c1 && c2){
					k1 = (l1.b.y-l1.a.y)/(l1.b.x-l1.a.x);
					b1 = l1.b.y-k1*l1.b.x;
					ans.x = l2.a.x;
					ans.y = k1*ans.x+b1;
				}else if(!c1 && !c2){
					k2 = (l2.b.y-l2.a.y)/(l2.b.x-l2.a.x);
					b2 = l2.b.y-k2*l2.b.x;
					k1 = (l1.b.y-l1.a.y)/(l1.b.x-l1.a.x);
					b1 = l1.b.y-k1*l1.b.x;
					ans.x = (b1-b2)/(k2-k1);
					ans.y = k1*ans.x+b1;
				}
				printf("POINT %.2lf %.2lf\n",ans.x,ans.y);
			}
		}
		printf("END OF OUTPUT\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值