NDK 1332 挑战

9 篇文章 0 订阅
7 篇文章 0 订阅

问题描述:

 桃花岛其实也没什么好玩的,黄蓉经常偷偷跑到江湖上与洪七公等人玩。于是,黄药师就 经常想一些游戏与女儿玩,为了是把黄蓉留在身边,江湖险恶啊!
 这次黄药师又想了一种模拟游戏,游戏是这样的:她把整个桃花岛划分成一个坐标系。游  戏开始前,黄蓉站在平面坐标系的一个点上,而她的闺房在坐标系的另一个点上,任何时  候,她可以从当前所在点跨一步达到她周围的上、下、左、右四个点,黄药师不断地说四  个字“东(E)”、“南(S)”、“西(W)”、“北(N)”,则黄蓉就想象着不断地从一个点走  到另一个点,直至到自己的闺房为止。

 比如,黄蓉开始时站在A点,她的家在B点,黄药师连续说了一串:  NNNENNWWWSSW,则走了如下一个线路。然后,黄药师会问黄蓉:中间有没有走“弯  路”了?即有没有捷径好走?比如,下图中就有多条捷径,可以从C走NN而到E,或走WW  直接到D。
  注意:捷径必须是直线。

数据输入:

 第一行是一个整数n( 3 <= n <= 250000)表示黄药师所报出的字符串长度。
 第二行是一个由N、E、S、W组成的字符串,都是大写字母且中间没有空格。
 我们把游戏的起点记为0,把黄蓉的闺房(即游戏的终点)记为n,中间的每一个落脚点都  依次标记一个自然数。

结果输出:

  输出只有一行,由3个数字和1个字符组成,中间用1个空格隔开。
 第1个数字表示最短捷径的长度。
 第2个数字表示最短捷径的开始点。
 第3个数字表示最短捷径的结束点。
 最后一个字符表示最短捷径的方向(同样用N、E、S、W中的一个表示)。
 如果最短捷径存在多个解,那么输出开始点标号最小的那一条。如果仍然有多个解,那么  输出结束点标号最大的。数据保证一定存在满足条件的最短捷径。

样例: 

 12
 NNNENNWWWSSW
2 3 11 W

核心思想:

 双快排,然后比较就好

type
 atp=record
 x,y,num:longint;
 end;
var
 a:array[-2..250010]of atp;
 n,st,ed,t1,t2,ans:longint;
 ch:char;
//==============================================================
procedure init;
var
 i:longint;
begin
 fillchar(a,sizeof(a),0);
 readln(n);
 fori:=1 to n do
 begin
  read(ch);
  a[i]:=a[i-1];
  a[i].num:=i;{<原位置>}
  case ch of
   'E':inc(a[i].y);{<求(x,y)坐标>}
   'W':dec(a[i].y);
   'N':inc(a[i].x);
   'S':dec(a[i].x);
  end;
 end;
end;
//==========================================================
procedure qsortx(l,r:longint);
var
 i,j:longint;
 k,t:atp;
begin
 i:=l;j:=r;
 k:=a[(l+r)shr 1];
 repeat
 while (a[i].x<k.x)or((a[i].x=k.x)and(a[i].y<k.y)) do inc(i);
 while (a[j].x>k.x)or((a[j].x=k.x)and(a[j].y>k.y)) do dec(j);
  ifi<=j then
  begin
   t:=a[i];a[i]:=a[j];a[j]:=t;
   inc(i);dec(j);
  end;
 until i>j;
 ifi<r then qsortx(i,r);
 ifj>l then qsortx(l,j);
end;
procedure qsorty(l,r:longint);
var
 i,j:longint;
 k,t:atp;
begin
 i:=l;j:=r;
 k:=a[(l+r)shr 1];
 repeat
 while (a[i].y<k.y)or((a[i].y=k.y)and(a[i].x<k.x)) do inc(i);
 while (a[j].y>k.y)or((a[j].y=k.y)and(a[j].x>k.x)) do dec(j);
  ifi<=j then
  begin
   t:=a[i];a[i]:=a[j];a[j]:=t;
   inc(i);dec(j);
  end;
 until i>j;
 ifi<r then qsorty(i,r);
 ifj>l then qsorty(l,j);
end;
//===========================================================
function pd(x,y,z:longint):boolean;{<按题目要求,先比长度再比开始点,最后比结束点>}
begin
 ifx<ans then exit(true);
 ifx>ans then exit(false);
 ifst>y then exit(true);
 ifst<y then exit(false);
 ifed<z then exit(true);
 exit(false);
end;
//==============================================================
procedure work1;
var
 i,j:longint;
 ct:char;
begin
 fori:=1 to n-1 do
  ifa[i].x=a[i+1].x then{<在同一行>}
  begin
   j:=a[i+1].y-a[i].y;{<列差即为路径长度>}
    if a[i].num<a[i+1].num then
     begin
      t1:=a[i].num;
      t2:=a[i+1].num;
      ct:='E';
     end
    else
     begin
      t1:=a[i+1].num;
      t2:=a[i].num;
      ct:='W';
     end;
    if t1+1=t2 then continue;{<若坐标并非按原序相连,则继续否则返回循环>}
    if pd(j,t1,t2) then
     begin
      ans:=j;
      st:=t1;
      ed:=t2;
      ch:=ct;
     end;
  end;
end;
//=============================================================
procedure work2;
var
 i,j:longint;
 ct:char;
begin
 fori:=1 to n-1 do
  ifa[i].y=a[i+1].y then
  begin
   j:=a[i+1].x-a[i].x;
    if a[i].num<a[i+1].num then
     begin
       t1:=a[i].num;
      t2:=a[i+1].num;
      ct:='N';
     end
    else
     begin
      t1:=a[i+1].num;
      t2:=a[i].num;
      ct:='S';
     end;
    if t1+1=t2 then continue;
    if pd(j,t1,t2) then
     begin
      ans:=j;
      st:=t1;
      ed:=t2;
      ch:=ct;
     end;
  end;
end;
//============================================================
procedure main;
begin
 ans:=maxlongint;
 qsortx(1,n);
 work1;{<横着的捷径>}
 qsorty(1,n);
 work2;{<竖着的捷径>}
 writeln(ans,' ',st,' ',ed,' ',ch);
end;
//============================================================
begin
 assign(input,'p1332.in');reset(input);
 assign(output,'p1332.out');rewrite(output);
 init;
 main;
 close(input);close(output);
end.
题目来源:NDK 1332

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值