JZOJ_4722. 跳楼机 (Standard IO)

Description

 
DJL为了避免成为一只咸鱼,来找srwudi学习压代码的技巧。
Srwudi的家是一幢h层的摩天大楼。由于前来学习的蒟蒻越来越多,srwudi改造了一个跳楼机,使得访客可以更方便的上楼。
经过改造,srwudi的跳楼机可以采用以下四种方式移动:
1、向上移动x层;
2、向上移动y层;
3、向上移动z层;
4、回到第一层。
一个月黑风高的大中午,DJL来到了srwudi的家,现在他在srwudi家的第一层,碰巧跳楼机也在第一层。DJL想知道,他可以乘坐跳楼机前往的楼层数。

Input

第一行一个整数h,表示摩天大楼的层数。
第二行三个正整数,分别表示题目中的x, y, z。

Output

一行一个整数,表示DJL可以到达的楼层数。

Solution

直接BFS,状态太多,我们考虑减少状态。
记di=c,表示在满足c mod x=i的前提下,仅通过第二和第三个操作可以到达的最小楼层c。
如果我们得到di,那么最后的答案就是
对于di的计算,我们有如下两种形式的转移
d(i+y) mod x=di+y
d(i+z) mod x=di+z
不难发现,这就是一个最短路模型,直接上SPFA。

代码

 1 type
 2   arr=record
 3     y,next,w:longint;
 4   end;
 5 var
 6   n,ans:int64;
 7   nm,xx,yy,zz:longint;
 8   a:array [0..200001] of arr;
 9   ls,list,v:array [0..100001] of longint;
10   d:array [0..100001] of int64;
11 procedure add(x,y,z:longint);
12 begin
13   inc(nm);
14   a[nm].y:=y; a[nm].w:=z;
15   a[nm].next:=ls[x]; ls[x]:=nm;
16 end;
17 
18 procedure init;
19 var
20   i,t:longint;
21 begin
22   fillchar(ls,sizeof(ls),255);
23   readln(n);
24   readln(xx,yy,zz);
25   if xx<yy then
26     begin
27       t:=xx; xx:=yy; yy:=t;
28     end;
29   if xx<zz then
30     begin
31       t:=xx; xx:=zz; zz:=t;
32     end;
33   nm:=0;
34   for i:=0 to xx-1 do
35     begin
36       add(i,(i+yy) mod xx,yy);
37       add(i,(i+zz) mod xx,zz);
38     end;
39 end;
40 
41 procedure spfa;
42 var
43   i,tail,head,x:longint;
44 begin
45   for i:=0 to 100001 do
46     d[i]:=9223372036854675807;
47   fillchar(v,sizeof(v),0);
48   head:=0; tail:=1;
49   list[1]:=1; d[1]:=1; v[1]:=1;
50   repeat
51     inc(head); x:=list[head];
52     i:=ls[x];
53     while i<>-1 do
54       with a[i] do
55         begin
56           if d[x]+w<d[y] then
57             begin
58               d[y]:=d[x]+w;
59               if v[y]=0 then
60                 begin
61                   inc(tail);
62                   list[tail]:=y;
63                   v[y]:=1;
64                 end;
65             end;
66           i:=next;
67         end;
68     v[list[head]]:=0;
69   until head>tail;
70 end;
71 
72 procedure print;
73 var
74   i:longint;
75 begin
76   ans:=0;
77   for i:=0 to xx-1 do
78     if n-d[i]>=0 then
79       ans:=ans+(n-d[i]) div xx+1;
80   writeln(ans);
81 end;
82 
83 begin
84   init;
85   spfa;
86   print;
87 end.
posted @ 2018-08-22 20:33  猪都哭了  阅读(247)  评论(0编辑  收藏  举报