大榕树——让我们共成长!
大榕树 myDrs.org
您的位置:大榕树 \ 编程       |  Logo语言   |  Pascal语言   |  信息学奥赛   |  高考保送    |  HTML版本
|  信息学奥赛>>解题报告>>ctsc2000《冰原探险》         本站全文搜索: 友情提示:

ctsc2000《冰原探险》
http://www.mydrs.org  3/1/2002  大榕树


[问题描述]
  给出各个冰山的位置,按照指定的规则将一个冰块推到指定的位置且步数最少。


[问题解法]
  很明显,该题必须搜索。应当采取的方法是广度。


广度的状态:
tstatus = record
     ibid : word; {冰山的序号}
     bor : byte; {在冰上的哪一侧,我们对冰山的上下左右4个侧面进行了编号}
    end;
  因为冰山没有相接的情况,所以可以不要记下具体的位置,对于同一个冰山的侧面的任何位置,朝固定方向推冰块的效果是一样的。


  这样在判重的时候也十分简单,只要用这样一个数组:
  already : array[1..4000, 1..4]of boolean
  already[i, j]表示第i个冰山的第j个侧面是否到达过。


  我们将目的地当作第n+1个冰山,这样在扩展的时候只要碰到第n+1个冰山就出解了。


[优化措施]
  对冰山按两个坐标轴的方向分别排序,可以进一步减少扩展时间。事实上,不要排序速度已经很快了。


[结论]
  该题是考察参赛者基本功的搜索题。

[参考程序]


{$R-,Q-}
const
 filein = 'ice.in';
 fileout = 'ice.out';
 up = 1;
 left = 2;
 right = 3;
 down = 4;
 move : array[1..4, 1..2]of byte = ((left, right), (up, down), (up, down),     (left, right));
 move2 : array[1..4, 1..2]of byte = ((up, down), (left, right), (left,      right), (up, down));
type
 ticeberg = record
     x1, y1, x2, y2 : integer;
    end;
 tstate = record
    ibid : word;
    bor : byte;
   end;
var
 already : array[1..4000, 1..4]of boolean;
 iceberg : array[1..4001]of ticeberg;
 a1, a2 : array[1..1000]of tstate;
 step, n, q1, q2 : word;
 srcx, srcy, tarx, tary : integer;
 time : longint;


procedure initialize;
var f : text; b : boolean; i : word;
begin
 assign(f, filein); reset(f);
 readln(f, n);
 readln(f, srcx, srcy);
 readln(f, tarx, tary);


 b := true;


 for i := 1 to n do
  with iceberg[i] do
   readln(f, x1, y1, x2, y2);
 close(f);


 with iceberg[n + 1] do
 begin
  x1 := tarx; x2 := x1;
  y1 := tary; y2 := y1;
 end;
end;


procedure out;
var f : text;
begin
 assign(f, fileout); rewrite(f);
 writeln(f, step);
 close(f);
 writeln((meml[$40: $6c] - time) / 18.2 : 0 : 2);
 halt;
end;


procedure expandsrc(p : byte; var p1, p2 : word);
var i, j : word;
 m1, m2 : integer;
begin
 p1 := 0; p2 := 0;
 j := 0;
 if (p = up) or (p = down) then
  begin
   m1 := -maxint; m2 := maxint;
   for i := 1 to n + 1 do
   begin
    if (iceberg[i].x1 <= srcx) and (iceberg[i].x2 >= srcx) then
    if (iceberg[i].y2 + 1 < srcy) and (iceberg[i].y2 + 1 > m1) then
    begin m1 := iceberg[i].y2; p1 := i; end;
    if (iceberg[i].x1 <= srcx) and (iceberg[i].x2 >= srcx) then
    if (iceberg[i].y1 - 1 > srcy) and (iceberg[i].y1 - 1 < m2) then
    begin m2 := iceberg[i].y1; p2 := i; end;
   end;
  end
 else
  begin
   m1 := -maxint; m2 := maxint;
   for i := 1 to n + 1 do
   begin
    if (iceberg[i].y1 <= srcy) and (iceberg[i].y2 >= srcy) then
    if (iceberg[i].x2 + 1 < srcx) and (iceberg[i].x2 + 1 > m1) then
    begin m1 := iceberg[i].x2; p1 := i; end;
    if (iceberg[i].y1 <= srcy) and (iceberg[i].y2 >= srcy) then
    if (iceberg[i].x1 - 1 > srcx) and (iceberg[i].x1 - 1 < m2) then
    begin m2 := iceberg[i].x1; p2 := i; end;
   end;
  end;
 if (p1 = n + 1) or (p2 = n + 1) then out;
end;


procedure expand(id : word; q : byte; var p1, p2 : word);
var i : word;
 x, y, m1, m2 : integer;
begin
 p1 := 0; p2 := 0;
 case q of
   up : begin x := iceberg[id].x1; y := iceberg[id].y1 - 1; end;
  down : begin x := iceberg[id].x2; y := iceberg[id].y2 + 1; end;
 right : begin x := iceberg[id].x2 + 1; y := iceberg[id].y2; end;
 left : begin x := iceberg[id].x1 - 1; y := iceberg[id].y1; end;
end;
if (q = left) or (q = right) then
 begin
  m1 := -maxint; m2 := maxint;
  for i := 1 to n + 1 do
  begin
   if (iceberg[i].x1 <= x) and (iceberg[i].x2 >= x) then
   if (iceberg[i].y2 + 1 < y) and (iceberg[i].y2 + 1 > m1) then
   begin m1 := iceberg[i].y2; p1 := i; end;
   if (iceberg[i].x1 <= x) and (iceberg[i].x2 >= x) then
   if (iceberg[i].y1 - 1 > y) and (iceberg[i].y1 - 1 < m2) then
   begin m2 := iceberg[i].y1; p2 := i; end;
  end;
 end
else
 begin
  m1 := -maxint; m2 := maxint;
  for i := 1 to n + 1 do
  begin
   if (iceberg[i].y1 <= y) and (iceberg[i].y2 >= y) then
   if (iceberg[i].x2 + 1 < x) and (iceberg[i].x2 + 1 > m1) then
   begin m1 := iceberg[i].x2; p1 := i; end;
   if (iceberg[i].y1 <= y) and (iceberg[i].y2 >= y) then
   if (iceberg[i].x1 - 1 > x) and (iceberg[i].x1 - 1 < m2) then
   begin m2 := iceberg[i].x1; p2 := i; end;
   end;
  end;
 if (p1 = n + 1) or (p2 = n + 1) then out;
end;


procedure firstexpand;
var i, b : byte;
 next1, next2 : word;
begin
 step := 1;
 for i := up to left do
begin
 expandsrc(i, next1, next2);
 b := 5 - move2[i, 1];
 if next1 <> 0 then
 begin
  inc(q1);
  a1[q1].ibid := next1;
  a1[q1].bor := b;
  already[next1, b] := true
 end;
 b := 5 - move2[i, 2];
 if next2 <> 0 then
  begin
   inc(q1);
   a1[q1].ibid := next2;
   a1[q1].bor := b;
   already[next2, b] := true
  end
 end;
end;


procedure mainexpand;
var i : word;
 j, b : byte;
 next1, next2 : word;
begin
 repeat
  inc(step);
  for i := 1 to q1 do
  begin
   expand(a1[i].ibid, a1[i].bor, next1, next2);
   b := 5 - move[a1[i].bor, 1];
   if next1 <> 0 then
    if not already[next1, b] then
    begin
     inc(q2);
     a2[q2].ibid := next1;
     a2[q2].bor := b;
     already[next1, b] := true
    end;
   b := 5 - move[a1[i].bor, 2];
   if next2 <> 0 then
    if not already[next2, b] then
    begin
     inc(q2);
     a2[q2].ibid := next2;
     a2[q2].bor := b;
     already[next2, b] := true
    end
   end;
   if q2 = 0 then break;
   a1 := a2; q1 := q2;
   q2 := 0;
  until false;
end;


procedure outfailed;
var f : text;
begin
 assign(f, fileout); rewrite(f);
 writeln(f, 0);
 close(f);
end;


begin
 time := meml[$40: $6c];


 initialize;
 firstexpand;
 mainexpand;
 outfailed;
end.


作 者:李翼
来 源:福建师大附中
共有1829位读者阅读过此文

  • 上篇文章第7次曙光信息学奥赛公告
  • 下篇文章ctsc2000《丘比特的烦恼》

  • 发送邮件
    保存页面 打印文章 HTML版本 发表评论

    □- 近期热门文章 □- 相关文章
    1. NOIP2006竞赛大纲 [8306]
    2. 七类高中生具有保送资格 [5910]
    3. NOI2006获奖选手名单 [4955]
    4. 关于举办NOIP2006模拟赛的通告 [4106]
    5. Turbo Pascal各语句运行速... [3594]
    6. Turbo王者归来新Delphi免费... [3181]
    7. IOI2006我国4名选手全部获得金... [2945]
    8. 关于APIO2007与IOI2007... [2763]
    9. noip倒计时 by 枯叶蝴蝶 [2683]
    10. 朱泽园:思想上的金牌更重要 [2168]
    CTSC2004结束IOI2004中国队产生
    CTSC2003因故取消
    CTSC2003将于5月中旬举行
    ctsc2000《丘比特的烦恼》2
    ctsc2000《快乐的蜜月》
    ctsc2000《丘比特的烦恼》
    ctsc2000《冰原探险》
     

    关于本站 | 合作伙伴 | 联系方式
    大榕树 版权所有 ©1999-2006 www.myDrs.org 闽ICP备05000721号