P1686 挑战 (模拟)

题目链接

前置知识

平面直角坐标系
x A = x B x_A=x_B xA=xB时,若( y A > y B y_A>y_B yA>yB), A B = y A − y B AB = y_A - y_B AB=yAyB,反之亦然。
y A = y B y_A=y_B yA=yB时,同理。

解题思路

在题目描述中,有这样一句话:

注意:捷径必须是直线。

所以,起点终点坐标要么 x x x坐标,要么 y y y坐标相同
那这道题就变得简单多了。
横纵坐标分别求一次就可以了,找到每一对 x x x y y y坐标相同的点,找到其中的最短距离即可。

注意:不能出现本来就可以由起点走向终点的“捷径”,即两点相邻(编号差值为1)的情况。
因为需要排序,我们开一个结构体存储每一个点的 x x x y y y坐标和编号

struct node{
	int x,y,id;
}s[250050];

排序x坐标

bool cmp1(node a,node b){
	return a.x<b.x||(a.x==b.x&&a.y<b.y);
}

排序y坐标,同理

接下来,讲代码的最最最最最重点部分,判断点与点之间是否有“捷径”,并存储符合题目的最优“捷径”。
这里结合分析南北方向上的“捷径”的代码注释进行分析

sort(s+1,s+1+n,cmp1); 
dista = 250005;
for(int i=1;i<n;i++){
	if(s[i].x!=s[i+1].x||abs(s[i].id-s[i+1].id)==1) continue;
	//两点x坐标不相同,无法形成捷径
	//两点相邻,无法形成捷径
	int d,sta,end;//sta 起点 end 终点
	char dire;//方向
	d = s[i+1].y - s[i].y;//两点距离
	if(s[i].id<s[i+1].id){
		sta = s[i].id;
		end = s[i+1].id;
		dire = 'N';
	}
	else{
		sta = s[i+1].id;
		end = s[i].id;
		dire = 'S';
	}
	if((d<dista) || (d==dista&&sta<id_start) || (d==dista&&sta==id_start&&end>id_end)){//若符合题目条件,存储
		dista = d;//最短距离
		id_start = sta;//最优捷径的起点
		id_end = end;//最优捷径的终点
		direction = dire;//最优捷径的方向
	}
}

东西方向上的分析同理,代码与上文代码相似,不再重复分析。

注意:本题在输入字符串时需要做判断是否为“NSEW”字符,否则可能会识别换行符,导致最终结果出错。

ch = getchar();
while(ch<'A'||ch>'Z') ch = getchar();

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
struct node{
	int x,y,id;
}s[250050];
int n,dista,id_start,id_end;
char direction;
bool cmp1(node a,node b){
	return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
bool cmp2(node a,node b){
	return a.y<b.y||(a.y==b.y&&a.x<b.x);
}
int main(){
	cin>>n;
	s[0].x = s[0].y = s[0].id = 0;
	for(int i=1;i<=n;i++){
		char ch;
		ch = getchar();
		while(ch<'A'||ch>'Z') ch = getchar();
		if(ch=='N'){
			s[i].x = s[i-1].x;
			s[i].y = s[i-1].y+1;
		}
		else if(ch=='S'){
			s[i].x = s[i-1].x;
			s[i].y = s[i-1].y-1;
		}
		else if(ch=='W'){
			s[i].x = s[i-1].x-1;
			s[i].y = s[i-1].y;
		}
		else if(ch=='E'){
			s[i].x = s[i-1].x+1;
			s[i].y = s[i-1].y;
		}
		s[i].id = i;
	}
	sort(s+1,s+1+n,cmp1); 
	dista = 250005;
	for(int i=1;i<n;i++){
		if(s[i].x!=s[i+1].x||abs(s[i].id-s[i+1].id)==1) continue;
		int d,sta,end;
		char dire;
		d = s[i+1].y - s[i].y;
		if(s[i].id<s[i+1].id){
			sta = s[i].id;
			end = s[i+1].id;
			dire = 'N';
		}
		else{
			sta = s[i+1].id;
			end = s[i].id;
			dire = 'S';
		}
		if((d<dista) || (d==dista&&sta<id_start) || (d==dista&&sta==id_start&&end>id_end)){
			dista = d;
			id_start = sta;
			id_end = end;
			direction = dire;
		}
	}
	
	sort(s+1,s+1+n,cmp2);
	for(int i=1;i<n;i++){
		if(s[i].y!=s[i+1].y||abs(s[i].id-s[i+1].id)==1) continue;
		int d,sta,end;
		char dire;
		d = s[i+1].x-s[i].x;
		if(s[i].id<s[i+1].id){
			sta = s[i].id;
			end = s[i+1].id;
			dire = 'E';
		}
		else{
			sta = s[i+1].id;
			end = s[i].id;
			dire = 'W';
		}
		if((d<dista) || (d==dista&&sta<id_start) || (d==dista&&sta==id_start&&end>id_end)){
			dista = d;
			id_start = sta;
			id_end = end;
			direction = dire;
		}
	}
	printf("%d %d %d %c",dista,id_start,id_end,direction);
	return 0;
}

版权说明:本文为博主原创文章,转载请附上本文链接(https://blog.csdn.net/smart_CZH/article/details/124775117)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值