TYVJ P1376 魔域之战

TYVJ P1376 魔域之战


描述

小A成功地在紧要关头逃离了神奇山洞,同时他也感觉自己rp大增。现在他站在了一座阴森森的城堡前,这就是江湖人称“死亡城堡”的魔域。为了rp,小A毅然决然地走了进去……
不愧是死亡城堡,险境丛生,小A又是一个大意的人,XXX他掉进了一个陷阱。
这是一个n*n的矩阵陷阱,矩阵的每一个小格内都有一个魔鬼,并且这些魔鬼属于不同的种类,种类数不超过p(1<=p<=n*n,有可能存在某一种魔鬼不在矩阵中出现)。每一种魔鬼i都有一种战斗力c[i],不同的魔鬼战斗力不同。打魔鬼也不是那么好玩的,需要消耗小A相应数量的战斗力。当小A打败了一个魔鬼后,此种类型的魔鬼就会全部消失,这样小A就可以自由的在这种类型的格子间传送,不会消耗任何的战斗力。每到一个格子,小A可以向紧邻的上下左右四个格子进发去打魔鬼,直到走出矩阵。小A开始郁闷了,他怎样才能从矩阵的第一行出发,顺利的走到矩阵的最后一行呢?所谓的顺利,就是使自己的战斗力大于0。
现在小A求助于聪明的你,希望你能求出小A顺利走出陷阱时剩余的最大战斗力。

输入输出


输入格式

第一行:两个整数n,p;
第2到n+1行是一个n*n的矩阵,矩阵中不同的数字代表不同的格子类型;
第n+2行是p个数,代表p种魔鬼的战斗力;
最后一行:小A的初始战斗力值W。

输出格式

一个整数表示小A顺利走出陷阱时剩余的最大战斗力,如果小A走不出陷阱就输出'Dangerous!';

样例


测试样例1


输入

样例一:

3 3
1 2 1
2 1 2
1 1 1
1 2 5
7


样例二:

3 3
1 2 1
2 1 2
3 3 3
1 2 5
2


输出

样例一:

6


样例二:

Dangerous!


备注

对于30%的数据:1<=n<=50
对于100%的数据:1<=n<=500;w<=maxlongint


分析

因为打败一种魔鬼后,该种魔鬼可以直接到达,所以我们可以在魔鬼种类中连边,只要矩阵中相邻的就连边,然后最后跑最短路即可。


代码如下

program p1376;
type point=^rec;
     rec=record
      e,v:longint;
      s:point;
     end;
     heaptype=record
      dist,doe:longint;
     end;
var i,j,n,m,ans:longint;
    map:array[1..500,1..500] of longint;
    fight:array[1..25002] of longint;
    heap:array[1..250002] of heaptype;
    ref:array[1..250002] of longint;
    visited:array[1..250002] of boolean;
    vertex:array[1..250002] of point;
procedure insert(s,e,v:longint);
var p:point;
begin
 new(p);
 p^.e:=e;
 p^.v:=v;
 p^.s:=vertex[s];
 vertex[s]:=p;
end;

procedure swap(i,j:longint);
var temp:heaptype;
begin
 temp:=heap[i];
 heap[i]:=heap[j];
 heap[j]:=temp;
 ref[heap[i].doe]:=i;
 ref[heap[j].doe]:=j;
end;

procedure go_up(st,j:longint);
var i:longint;
begin
 while (j>>1)>=st do
  begin
   i:=j>>1;
   if heap[i].dist>heap[j].dist
    then
     begin
      swap(i,j);
      j:=i;
     end
    else break;
  end;
end;

procedure go_down(i,ed:longint);
var j:longint;
begin
 while (i<<1)<=ed do
  begin
   j:=i<<1;
   if (j<ed) and (heap[j].dist>heap[j+1].dist) then inc(j);
   if heap[i].dist>heap[j].dist
    then
     begin
      swap(i,j);
      i:=j;
     end
    else break;
 end;
end;

procedure dijkstra;
var i,total:longint;
    p:point;
begin
 total:=m+2;
 for i:=1 to m+2 do
  begin
   heap[i].doe:=i;
   heap[i].dist:=maxlongint;
   ref[i]:=i;
  end;
 heap[1].dist:=0;
 while (total>0) and (not visited[m+2]) and (heap[1].dist<>maxlongint) do
  begin
   p:=vertex[heap[1].doe];
   while p<>nil do
    begin
     if heap[ref[p^.e]].dist>heap[1].dist+p^.v
      then
       begin
        heap[ref[p^.e]].dist:=heap[1].dist+p^.v;
        go_up(1,ref[p^.e]);
       end;
     p:=p^.s;
    end;
   visited[heap[1].doe]:=true;
   swap(1,total);
   dec(total);
   go_down(1,total);
  end;
end;

begin
 readln(n,m);
 for i:=1 to n do
  for j:=1 to n do
   begin
    read(map[i,j]);
    map[i,j]:=map[i,j]+1;
   end;
 for i:=1 to m do
  begin
   read(fight[i+1]);
   visited[i]:=false;
  end;
 visited[m+1]:=false;
 visited[m+2]:=false;
 for i:=1 to n do
  for j:=1 to n do
   begin
    if (i>1)
     then
      begin
       insert(map[i-1,j],map[i,j],fight[map[i-1,j]]);
       insert(map[i,j],map[i-1,j],fight[map[i,j]]);
      end;
    if (j>1)
     then
      begin
       insert(map[i,j-1],map[i,j],fight[map[i,j-1]]);
       insert(map[i,j],map[i,j-1],fight[map[i,j]]);
      end;
    if (i=1)
     then
      begin
       insert(1,map[i,j],0);
      end;
    if (i=n)
     then
      begin
       insert(map[i,j],m+2,fight[map[i,j]]);
      end;
   end;
 dijkstra;
 readln(ans);
 ans:=ans-heap[ref[m+2]].dist;
 if ans<0 then write('Dangerous!')
          else write(ans);
end.

评测结果

#0: Accepted (0ms, 6248KiB)

#1: Accepted (0ms, 6284KiB)

#2: Accepted (0ms, 6396KiB)

#3: Accepted (0ms, 6860KiB)

#4: Accepted (31ms, 8796KiB)

#5: Accepted (46ms, 11936KiB)

#6: Accepted (78ms, 14900KiB)

#7: Accepted (46ms, 16400KiB)

#8: Accepted (140ms, 22044KiB)

#9: Accepted (124ms, 22040KiB)

Capture&Seek

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值