原题链接
题目大意
有一条路径,使用
E
,
W
,
S
,
N
E,W,S,N
E,W,S,N 来表示(
E
E
E 向东,
W
W
W 向西,
S
S
S 向南,
N
N
N 向北)。找一条最短的捷径可以连接其中非连续的两点(捷径必须是直的,并且起始点和终止点的x或y坐标相同),若有多个答案,输出开始点标号最小的那一条,若任然有多个答案,输出结束点标号最大的那一条,如:
答案即是:
解题思路
题目描述中,显眼的括号告诉了我们答案:
(捷径必须是直的,并且起始点和终止点的x或y坐标相同)
如何让起始点和终止点的x坐标相同?很简单,只需要按照x坐标当做第一关键字排一次序。如何让起始点和终止点的y坐标相同?也只需要按照y坐标当做第一关键字排一次序。
那么到底输出什么答案?其实,也只需要按照题目意思(求最短的捷径,若有多个答案,输出开始点标号最小的那一条,若任然有多个答案,输出结束点标号最大的那一条)再排一次序。
代码实现
//注意:本代码中x,y坐标表示的意义相反
#include<iostream>
#include<fstream>
#include<set>
#include<map>
#include<ctime>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;
struct node{
ll x,y,id;
} xy[250010];
struct node2{
ll lenth,s,e;
char way;
};
struct node3{
ll x,y;
};
vector<node2> ans;
char c;
char ans_way;
int ans_len=0x7fffffff,ans_b=-0x7fffffff,ans_a=0x7fffffff,n;
node chk(char c)
{
return ((c=='E')?(node){0,1}:((c=='W')?(node){0,-1}:((c=='S')?(node){1,0}:(node){-1,0})));
}
bool pd1(node q,node h)
{
if(q.x!=h.x)
return q.x<h.x;
return q.y<h.y;
}
bool pd2(node q,node h)
{
if(q.y!=h.y)
return q.y<h.y;
return q.x<h.x;
}
bool pd3(node2 q,node2 h)
{
if(q.lenth!=h.lenth)//长度最短
return q.lenth<h.lenth;
if(q.s!=h.s)//开始点标号最小
return q.s<h.s;
return q.e>h.e;//结束点标号最大
}
char chk_ans(node3 q,node3 h)//q为起始点,h为终止点,判断路线方向
{
if(q.x<h.x)
return 'S';//向南
if(q.x>h.x)
return 'N';//向北
if(q.y<h.y)
return 'E';//向东
return 'W';//向西
}
void work1()//寻找朝向东或西的捷径
{
for(int i=1;i<n;i++){
if(xy[i].x==xy[i+1].x&&min(xy[i].id,xy[i+1].id)+1!=max(xy[i].id,xy[i+1].id)){
if(xy[i].id<xy[i+1].id)//判断起始点和终止点
ans.push_back((node2){abs(xy[i].y-xy[i+1].y),xy[i].id,xy[i+1].id,chk_ans((node3){xy[i].x,xy[i].y},(node3){xy[i+1].x,xy[i+1].y})});//记录答案
else
ans.push_back((node2){abs(xy[i].y-xy[i+1].y),xy[i+1].id,xy[i].id,chk_ans((node3){xy[i+1].x,xy[i+1].y},(node3){xy[i].x,xy[i].y})});//记录答案
}
}
}
void work2()//寻找朝向南或北的捷径
{
for(int i=1;i<n;i++){
if(xy[i].y==xy[i+1].y&&min(xy[i].id,xy[i+1].id)+1!=max(xy[i].id,xy[i+1].id)){//y坐标相同,且非向连续
if(xy[i].id<xy[i+1].id)//判断起始点和终止点
ans.push_back((node2){abs(xy[i].x-xy[i+1].x),xy[i].id,xy[i+1].id,chk_ans((node3){xy[i].x,xy[i].y},(node3){xy[i+1].x,xy[i+1].y})});//记录答案
else
ans.push_back((node2){abs(xy[i].x-xy[i+1].x),xy[i+1].id,xy[i].id,chk_ans((node3){xy[i+1].x,xy[i+1].y},(node3){xy[i].x,xy[i].y})});//记录答案
}
}
}
int main()
{
cin>>n;
xy[0].x=250005;
xy[0].y=250005;
for(int i=1;i<=n;i++){
cin>>c;
node change=chk(c);
xy[i].x=xy[i-1].x+change.x;//模拟路径
xy[i].y=xy[i-1].y+change.y;//模拟路径
xy[i].id=i;
}
sort(xy+1,xy+n+1,pd1);//以x为第一关键字排序
work1();
sort(xy+1,xy+n+1,pd2);//以y为第一关键字排序
work2();
sort(ans.begin(),ans.end(),pd3);//排序答案
cout<<ans[0].lenth<<" "<<ans[0].s<<" "<<ans[0].e<<" "<<ans[0].way;
return 0;
}
样例
输出
12
NNNENNWWWSSW
输出
2 3 11 W