2012年复赛综合训练(一):第一题: …

第一题: 穿越封锁线cross.pas/c/cpp

题目描述:

对于窃取情报和破译密码,Feli简直就是天才!

Feli知道我军3721整编军是我军一支重点培养的生力军,如果在这次行动中遭受损失,那对我军将是一个十分严重的实力打击。这么重要的消息,必须赶紧传达到指挥步!由于抗战期间交通十分落后,Feli只好委托Lucky连夜将该消息送达总部。接到委托,Lucky立即启程。

从情报站到指挥部之间有许多错综交叉的道路,道路和道路的交叉处都有地方可以供Lucky躲藏。由于这里是交通要道,敌人也对这个地带十分关注:他们会时不时对在某些道路上派人巡逻。虽然Lucky可以用精准的枪法将他们干掉,但是现在身负重任,不能打草惊蛇,所以必须避开他们。这意味着,如果某条道路有人巡逻,那么Lucky将无法穿过。时间紧迫,Lucky必须尽快到达总部。现在Lucky再次向你求助,他应该如何行走才能用最短的时间到达指挥部。

说明:在每个交叉路口,Lucky都能选择躲藏和行走。敌人的巡逻是周期循环的,他们总是以分钟为单位巡逻某条道路,在该分钟过去后离开。针对每条道路,我们假设Lucky总是刚好用1分钟时间走完。

针对下列数据:

V={1,2,3,4,5};  E={(1,2),(2,3),(3,4),(2,4),(4,5),(1,3),(3,5)}

结点1为情报站,5为指挥部,其余为交叉路口。

周期为4分钟。

每个周期的第1分钟有巡逻的边为{(1,2),(2,4),(4,5)}

每个周期的第2分钟有巡逻的边为{(1,3),(2,3),(3,5)}

每个周期的第3分钟有巡逻的边为{(3,4),(4,5)}

每个周期的第4分钟没有巡逻边。

这样,Lucky可以在第一分钟走边(1,3),第二分钟躲藏,第3分钟走边(3,5),消耗3分钟,时间最短。

数据说明:

每组输入数据第一行有2个整数n和m(1≤n≤100; 1≤m≤500),代表地图有n个结点m条边。1号结总是代表情报站,n号结点总是代表指挥部。

接下去m行是对地图的描述,每行有2个小于n的整数,分别代表一条边两端的结点编号。(如果边被重复描述,仍表示只有一条边)。

再接下去一行有一个整数k(0≤k≤10)代表周期长度。

后来的数据都是对周期巡逻边的描述,每行有2个整数,表示被关注的边。0 0则表示对周期中某一分钟的巡逻边描述结束。数据保证在该段恰存在k个0 0。

 

输出数据仅有一行,如果Lucky可以到达指挥部,则输出到达指挥部的最短时间。如果不能到达则输出“No solution.”

样例输入(cross.in):

5 7

1 2

2 3

3 4

2 4

4 5

1 3

3 5

4

1 2

2 4

4 5

0 0

1 3

2 3

3 5

0 0

3 4

4 5

0 0

0 0

样例输出(cross.out):

3

 

 

一开始思路是对的,但是初值赋错了,只过了4个点。

程序写的很乱,变量名很不科学。

 

var
 n,m,k:longint;
 a:array[1..500+1,1..500+1,0..10+1]of longint;
 d:array[1..100+1,0..10+1]of longint;
 mark:array[1..100+1,0..10+1]of boolean;

procedure init;
var
 i,x,y:longint;
begin
 read(n,m);
 for i:=1 to m do
   begin
   read(x,y);
   a[x,y,0]:=1;
   a[y,x,0]:=1;
   end;
 read(k);
 for i:=1 to k do
  begin
  while true do
   begin
   read(x,y);
   if (x=0)and(y=0) then break;
   a[x,y,i]:=-1;
   a[y,x,i]:=-1;
   end;
  end;
end;

procedure main;
var
 i,j,kk,kkk,min,mini:longint;
begin
 for i:=2 to 100+1 do
  for j:=0 to 11 do d[i,j]:=maxlongint div 2;
 fillchar(mark,sizeof(mark),0);
 for j:=1 to 11 do begin d[1,j]:=j;  end;

 while true do
  begin
     min:=maxlongint div 2;
     for i:=1 to n do
      for j:=0 to k do
      if (d[i,j]<min)and(mark[i,j]=false) then begin min:=d[i,j]; mini:=i; kk:=j; end;
     if min=maxlongint div 2 then exit;
     mark[mini,kk]:=true;

  if k<>0 then kkk:=(kk) mod k+1
          else kkk:=0;

  for i:=1 to n do
   if not mark[i,kkk] then
   if (a[mini,i,0]+a[mini,i,kkk]>0) and(d[mini,kk]+1<d[i,kkk]) then
     begin
     d[i,kkk]:=d[mini,kk]+1;
     for j:=kkk+1 to k do
      if d[i,kkk]+(j-kkk)<d[i,j] then d[i,j]:=d[i,kkk]+j-kkk;
     for j:=1 to kkk-1 do
      if d[i,kkk]+(j-kkk+k)<d[i,j] then d[i,j]:=d[i,kkk]+j-kkk+k;
     end;
  end;
end;

procedure print;
var
 i,min:longint;
begin
 min:=maxlongint div 2;
 for i:=0 to k do
  if d[n,i]<min then min:=d[n,i];

 if min=maxlongint div 2 then writeln('No solution.')
 else
 write(min);
end;

begin
 assign(input,'cross.in');
 assign(output,'cross.out');
 reset(input);
 rewrite(output);
 init;
 main;
 print;
 close(input);
 close(output);
end.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值