poj1696 Space Ant

本文探讨了一种独特的寻径算法,旨在通过螺旋路径访问第一象限内的多个点,确保覆盖所有区域并实现最优路径规划。算法通过巧妙地利用点积和距离计算,动态选择下一个访问点,最终输出访问的植物数量和访问顺序。

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

        题意:一只蚂蚁,爬行时不能右转,不能经过自己爬过的路径。它去吃坐标系(第一象限)里的一些植物,起点在x=0,y=植物的最小纵坐标处。问以什么顺序吃,能吃到最多,输出吃到的植物数和顺序。

        思路:其实,蚂蚁一定能吃到所有的植物,这是个坑。它的爬行轨迹是一条螺旋线,能经过所有的点。y最小中x最小的点肯定是第一个点,初始方向为x轴正方向。维护一个当前方向(或者说是上一个点和当前点),然后枚举每一个没有经过的点,拐角(利用点积的性质计算,因为角的范围是[0,pi],余弦函数在此区间单调)最小的为下一个点,如果多个点拐角相等(浮点数不好直接比较,另写一个函数),则选择最近的点。


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>

using namespace std;

struct point{
	int x;
	int y;
	
};

point pt[110];
bool used[110];

bool equal(double a,double b){//绝对值很小认为相等
	if(abs(a-b)<0.000001)return true;
	return false;
}
int dp(int x1,int y1,int x2,int y2){//点积
	return (x1*x2+y1*y2);
}
double dist(point p1,point p2){//
	return sqrt(((double)p1.x-p2.x)*(p1.x-p2.x)+((double)p1.y-p2.y)*(p1.y-p2.y));
}


int main(){
	int M;
	cin>>M;
	while(M--){
		memset(used,0,sizeof(used));
		int N;
		cin>>N;
		int starty=INT_MAX;
		int startx;
		int starti;
		for(int i=1;i<=N;i++){
			int a;
			cin>>a;
			cin>>pt[a].x>>pt[a].y;
			if(pt[a].y<starty){
				starty=pt[a].y;startx=pt[a].x;starti=i;
			}
		}
		
		used[starti]=true;
		point last;
		last.x=0;last.y=starty;
		point cur;
		cur.x=startx;cur.y=starty;
		
		cout<<N<<" "<<starti<<" ";
		for(int i=1;i<N;i++){
			double maxangle=-1.1;
			int key;
			for(int j=1;j<=N;j++){
				if(used[j])continue;
				
				int dpval=dp(cur.x-last.x,cur.y-last.y, pt[j].x-cur.x,pt[j].y-cur.y);
				if(equal(dpval/dist(last,cur)/dist(cur,pt[j]),maxangle)){
					if(dist(cur,pt[j])<dist(cur,pt[key])){
						maxangle=dpval/dist(last,cur)/dist(cur,pt[j]);
						key=j;
					}
					continue;
				}
				if(dpval/dist(last,cur)/dist(cur,pt[j])>maxangle){
					maxangle=dpval/dist(last,cur)/dist(cur,pt[j]);
					key=j;
				}
			}
			last.x=cur.x;last.y=cur.y;
			cur.x=pt[key].x;cur.y=pt[key].y;
			used[key]=true;
			cout<<key;
			if(i==(N-1)){
				cout<<endl;
			}else{
				cout<<" ";
			}
		}
		
	} 
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值