和bzoj2595类似,也是斯坦纳树
设f[l,r,]表示在点i机器人组合成了l-r最少推的次数,然后可得
f[l,r,i]=min(f[l,m,i]+f[m+1,r,i])
f[l,r,i]=min(f[l,r,j]+1) 点j能推到i
但是这样做肯定会TLE,考虑两个优化
首先,一开始其实有很多根本用不到,我们可以先从机器人初始位置搜下去,找到所有可以访问的点做dp即可
其次,观察第二个方程,它的边权都是1,我们一定要用spfa转移吗?不,我们可以用直接宽搜
具体的我们维护两个队列,第一个队列是初始的按从小到大排,新加入的点放在第二个队列,每次取两个队头小的那一个
但我还是tle,求神犇指教
1 const dx:array[1..4] of longint=(0,1,0,-1); 2 dy:array[1..4] of longint=(1,0,-1,0); 3 inf=1000000007; 4 type node=record 5 x,y:longint; 6 end; 7 8 var w:array[0..250010] of node; 9 q1,q2,st:array[0..250010] of longint; 10 po:array[0..501,0..501,1..4] of longint; 11 f:array[0..250010,0..9,0..9] of longint; 12 c:array[0..501,0..501] of char; 13 v:array[0..250010] of boolean; 14 loc:array[0..250010] of longint; 15 next:array[0..250010,1..4] of longint; 16 s:array[0..100010] of longint; 17 mid,h1,t1,i,j,p,q,l,x,y,k,n,m,ans,mx,tot:longint; 18 19 function min(a,b:longint):longint; 20 begin 21 if a>b then exit(b) else exit(a); 22 end; 23 24 function dfs(x,y,k:longint):longint; 25 var xx,yy:longint; 26 begin 27 if (po[x,y,k]=0) then exit(-1); 28 if po[x,y,k]>0 then exit(po[x,y,k]); 29 po[x,y,k]:=0; 30 xx:=x+dx[k]; 31 yy:=y+dy[k]; 32 if (xx<1) or (xx>n) or (yy<1) or (yy>m) or (c[xx,yy]='x') then po[x,y,k]:=(x-1)*m+y 33 else if c[xx,yy]='A' then po[x,y,k]:=dfs(xx,yy,(k+2) mod 4+1) 34 else if c[xx,yy]='C' then po[x,y,k]:=dfs(xx,yy,k mod 4+1) 35 else po[x,y,k]:=dfs(xx,yy,k); 36 exit(po[x,y,k]); 37 end; 38 39 function cmp(i,j,l,r:longint):boolean; 40 begin 41 exit(f[i,l,r]<f[j,l,r]); 42 end; 43 44 procedure sort(l,r:longint); 45 var i:longint; 46 begin 47 for i:=1 to mx do 48 inc(s[i],s[i-1]); 49 for i:=t1 downto 1 do 50 begin 51 q1[s[f[st[i],l,r]]]:=st[i]; 52 dec(s[f[st[i],l,r]]); 53 end; 54 end; 55 56 procedure bfs(l,r:longint); 57 var h2,t2,i,x,y:longint; 58 begin 59 h2:=1; 60 t2:=0; 61 while (h2<=t2) or (h1<=t1) do 62 begin 63 if (h2>t2) or (h1<=t1) and cmp(q1[h1],q2[h2],l,r) then 64 begin 65 x:=q1[h1]; 66 inc(h1); 67 end 68 else begin 69 x:=q2[h2]; 70 inc(h2); 71 end; 72 v[x]:=true; 73 for i:=1 to 4 do 74 begin 75 if next[x,i]=0 then continue; 76 y:=next[x,i]; 77 if not v[y] and (f[x,l,r]+1<f[y,l,r]) then 78 begin 79 v[y]:=true; 80 f[y,l,r]:=f[x,l,r]+1; 81 inc(t2); 82 q2[t2]:=y; 83 end; 84 end; 85 end; 86 end; 87 88 begin 89 readln(k,m,n); 90 for i:=1 to n*m do 91 for p:=1 to k do 92 for q:=1 to k do 93 f[i,p,q]:=inf; 94 for i:=1 to n do 95 begin 96 for j:=1 to m do 97 begin 98 read(c[i,j]); 99 if (c[i,j]>='1') and (c[i,j]<='9') then 100 begin 101 x:=ord(c[i,j])-48; 102 inc(t1); 103 w[t1].x:=i; w[t1].y:=j; 104 f[t1,x,x]:=0; 105 loc[(i-1)*m+j]:=t1; 106 end; 107 end; 108 readln; 109 end; 110 fillchar(po,sizeof(po),255); 111 h1:=1; 112 while h1<=t1 do 113 begin 114 x:=w[h1].x; y:=w[h1].y; 115 for i:=1 to 4 do 116 begin 117 if po[x,y,i]=-1 then 118 begin 119 po[x,y,i]:=dfs(x,y,i); 120 if (po[x,y,i]>0) and (loc[po[x,y,i]]=0) then 121 begin 122 inc(t1); 123 w[t1].x:=(po[x,y,i]-1) div m+1; 124 w[t1].y:=(po[x,y,i]-1) mod m+1; 125 loc[po[x,y,i]]:=t1; 126 end; 127 end; 128 if po[x,y,i]>0 then next[h1,i]:=loc[po[x,y,i]]; 129 end; 130 inc(h1); 131 end; 132 tot:=t1; 133 for l:=1 to k do 134 for p:=1 to k-l+1 do 135 begin 136 q:=p+l-1; 137 h1:=1; t1:=0; mx:=0; 138 for i:=1 to tot do 139 begin 140 v[i]:=false; 141 for mid:=p to q-1 do 142 f[i,p,q]:=min(f[i,p,q],f[i,p,mid]+f[i,mid+1,q]); 143 if f[i,p,q]<inf then 144 begin 145 inc(t1); 146 st[t1]:=i; 147 inc(s[f[i,p,q]]); 148 if f[i,p,q]>mx then mx:=f[i,p,q]; 149 end; 150 end; 151 sort(p,q); 152 for i:=0 to mx do 153 s[i]:=0; 154 bfs(p,q); 155 end; 156 ans:=inf; 157 for i:=1 to tot do 158 ans:=min(ans,f[i,1,k]); 159 if ans>=inf then writeln(-1) 160 else writeln(ans); 161 end.