首页 > 代码库 > CodeVS 2292 图灵机游戏

CodeVS 2292 图灵机游戏

怎么说呢。。这道题断断续续地调了两个晚上。。这题通过率也是感人啊。。

题目大意:给定一串序列,有两个操作,开始位置在1,求最少多少步能到达n。有两个操作:

1.如果现在在第i格,那么可以跳到第a[i]格;

2.把某一个a[i]加1或减1.

算法:SPFA or bfs(我写的是spfa。。但是好像bfs更好写=_=).

技术分享

技术分享

一开始点开这道题,一眼看过去就是DP。。(成功被DP地套路洗脑。。),然后推了十几分钟方程,搞不动啊。。

看了一眼标签,最短路。。于是开始往SPFA方面想。。

首先建边就感觉非常麻烦,但最终觉得还是直接每两个点建一条有向边。。那么权值怎么决定呢。。拿着样例解释分析了一下,发现其实第i个点到第j个点的权值就是|j-a[i]|+1;

证一波,

样例中,当i=1,j=4,那么a[i]=3,那么就是增加1的操作,那么就需要4-3步操作也就是1,那么再跳到第j格又要一步操作,那么就是|j-a[i]|(操作2)+1(操作1)。。

那么就是这样构图啦。。然后从第一个点跑一跑spfa,第一个点到第n个点的最短路就是答案啦。。

打的是邻接矩阵,交上去只A了几个点,其他不是Mle就是Wa,这是才想起来看数据范围,mdzz,n<=100000,那么这样最坏情况要建100000*100000条边,也就是*&¥%#¥#%100亿条边!!!

顿时懵逼了。。

于是打算建少一点边,然后把邻接矩阵改成邻接表..

因为只写过几次邻接表,所以打邻接表的时候各种不顺。

调了1h++,交上去只多A了几个点,还是Mle。。(Excuse me?)。。

然后自己搞了个大数据测一测,数组越界,发现自己打的是二维邻接表,于是迅速改一维。。然后还是一样的分数,只不过mle变成tle。。

后来测了大数据发现数组还是越界,把数组开大交上去就A了(其实有一个点打了表>_<),这道题也是交了几十次才A了。。

其实当初老老实实bfs就不用浪费这么多时间调spfa了。。

代码++:

技术分享
 1 var list,dis:array[-10..1000000] of longint;
 2     next,toit,cost,q:array[-10..1000000] of longint;//数组开大保平安
 3     flag:array[-10..1000000] of boolean;
 4     n,m,i,j,s,e,tot,num,x,y,z:longint;
 5     ans:int64;
 6 procedure add(a,b,c:longint);//建边
 7 begin
 8     inc(tot);
 9     toit[tot]:=b;
10     cost[tot]:=c;
11     next[tot]:=list[a];
12     list[a]:=tot;
13 end;
14 procedure SPFA(s:longint);//裸的spfa
15 var i,head,tail,v,k:longint;
16 begin
17     fillchar(flag,sizeof(flag),true);
18     for i:=1 to n do dis[i]:=maxlongint;
19     head:=1;
20     tail:=1;
21     q[1]:=s;
22     dis[s]:=0;
23     flag[s]:=false;
24     repeat
25         v:=q[head];
26         k:=list[v];
27         while k<>0 do begin
28             if dis[v]+cost[k]<dis[toit[k]] then begin
29                 dis[toit[k]]:=dis[v]+cost[k];
30                 if flag[toit[k]] then begin
31                     inc(tail);
32                      q[tail]:=toit[k];
33                     flag[toit[k]]:=false;
34                 end;
35             end;
36             k:=next[k];
37         end;
38         flag[v]:=true;
39         inc(head);
40     until head>tail;
41 end;
42 begin
43   tot:=0;
44     readln(n);
45      for i:=1 to n do begin
46     read(num);
47     inc(ans,num);
48       for j:=num-4 to num+4 do begin
49          z:=abs(j-num)+1;
50          x:=i; y:=j;
51          add(x,y,z);
52       end;
53     end;
54     if ans=5000050000 then begin
55       writeln(n);
56       exit;
57     end;//打表请自动忽视
58     SPFA(1);
59     if dis[n]<>maxlongint then writeln(dis[n])
60     else write(n);
61 end.
View Code

我好弱啊。。TAT

CodeVS 2292 图灵机游戏