Silver
题解:之前的题解中,采用的是\(O\left({25}^{7} \right)\)的简单暴力枚举,虽然能A,我一直认为还有更灵活的办法可以去做,于是有了这个第二篇题解
这次的思路是:每次先找一个点,然后向这个点的四周进行扩张,每一层dfs在原有的块的基础上再向外扩张一个,最终形成的块必然是7个连续的格子,应该能够起到比较好的优化效果——因为我每次选取扩张的点,都是通过动态维护当前块周围一圈的点来进行的,对于联通块而言,在地图内最多只能有15个周围的点,所以复杂度一下子降到了\(O\left({15}^{7} \right)\),并且完全不需要判断7个点是否构成一块。。。
以上是优点,但是这样一来仔细想想,缺点也十分明显——由于对于同样一个图形而言,可以由很多中扩张顺序可以形成,所以势必造成巨大的重复计算,这是个致命的伤。。。所以只好进行判重,所以只好又写了个双值哈希,确保一种选取情况对应一对唯一的哈希值,而对于一大堆乱七八糟的哈希值对,怎样判断是否存在呢?于是逗比的我又来个了平衡树进行查找,这样子算下来,时间复杂度 \(O\left({15}^{7}\times 7 Ans \log Ans \right)\)
1 /**************************************************************
2 Problem: 1675
3 User: HansBug
4 Language: Pascal
5 Result: Accepted
6 Time:2524 ms
7 Memory:2964 kb
8 ****************************************************************/
9
10 const p=314159;q=951413;
11 type
12 pair=record
13 a0,b0:int64;
14 end;
15 var
16 i,j,k,l,m,n,head,tot,ans,av:longint;
17 lef,rig,fix:array[0..100000] of longint;
18 b:array[0..100000,1..2] of int64;
19 c,d:array[0..100,1..2] of longint;
20 a,e:array[0..10,0..10] of longint;
21 list:array[0..25,1..2] of int64;
22 ch:char;
23 procedure rt(var x:longint);
24 var l,f:longint;
25 begin
26 if (x=0) or (lef[x]=0) then exit;
27 f:=x;l:=lef[x];
28 lef[f]:=rig[l];
29 rig[l]:=f;
30 x:=l;
31 end;
32 procedure lt(var x:longint);
33 var r,f:longint;
34 begin
35 if (x=0) or (rig[x]=0) then exit;
36 f:=x;r:=rig[x];
37 rig[f]:=lef[r];
38 lef[r]:=f;
39 x:=r;
40 end;
41 function ins(var x:longint;y:longint):boolean;
42 begin
43 ins:=true;
44 if x=0 then
45 begin
46 x:=y;
47 exit;
48 end;
49 if (b[y,1]<b[x,1]) or ((b[y,1]=b[x,1]) and (b[y,2]<b[x,2])) then
50 begin
51 if lef[x]=0 then lef[x]:=y else ins:=ins(lef[x],y);
52 if fix[lef[x]]<fix[x] then rt(x);
53 end
54 else if (b[y,1]>b[x,1]) or ((b[y,1]=b[x,1]) and (b[y,2]>b[x,2])) then
55 begin
56 if rig[x]=0 then rig[x]:=y else ins:=ins(rig[x],y);
57 if fix[rig[x]]<fix[x] then lt(x);
58 end
59 else exit(false);
60 end;
61 function checkhash(t:pair):boolean;
62 begin
63 inc(tot);
64 b[tot,1]:=t.a0;b[tot,2]:=t.b0;
65 lef[tot]:=0;rig[tot]:=0;fix[tot]:=random(maxlongint);
66 checkhash:=ins(head,tot);
67 if not(checkhash) then dec(tot);
68 end;
69 function trans(x,y:longint):longint;
70 begin
71 trans:=(x-1)*5+y;
72 end;
73 function hashstate:pair;
74 var
75 i,j:longint;x,y:int64;t:pair;
76 begin
77 x:=0;y:=0;
78 for i:=1 to 7 do
79 begin
80 j:=trans(c[i,1],c[i,2]);
81 x:=(x+list[j,1]) mod q;
82 y:=(y+list[j,2]) mod p;
83 end;
84 t.a0:=x;t.b0:=y;
85 exit(t);
86 end;
87 procedure hashstartup;
88 var i:longint;
89 begin
90 list[0,1]:=1;list[0,2]:=1;
91 for i:=1 to 25 do
92 begin
93 list[i,1]:=(list[i-1,1]*p) mod q;
94 list[i,2]:=(list[i-1,2]*q) mod p;
95 end;
96 end;
97 procedure dfs(z:longint);
98 var i,j,k,l:longint;
99 begin
100 if z>7 then
101 begin
102 j:=0;
103 for i:=1 to 7 do inc(j,a[c[i,1],c[i,2]]);
104 if j<=3 then exit;
105 if checkhash(hashstate) then
106 begin
107 inc(ans);
108 end;
109 exit;
110 end;
111 l:=av;
112 for i:=1 to l do
113 begin
114 if e[d[i,1],d[i,2]]<>1 then continue;
115 c[z,1]:=d[i,1];c[z,2]:=d[i,2];
116 e[d[i,1],d[i,2]]:=2;
117 if e[d[i,1]-1,d[i,2]]=0 then
118 begin
119 inc(av);
120 d[av,1]:=d[i,1]-1;
121 d[av,2]:=d[i,2];
122 e[d[i,1]-1,d[i,2]]:=1;
123 end;
124 if e[d[i,1]+1,d[i,2]]=0 then
125 begin
126 inc(av);
127 d[av,1]:=d[i,1]+1;
128 d[av,2]:=d[i,2];
129 e[d[i,1]+1,d[i,2]]:=1;
130 end;
131 if e[d[i,1],d[i,2]-1]=0 then
132 begin
133 inc(av);
134 d[av,1]:=d[i,1];
135 d[av,2]:=d[i,2]-1;
136 e[d[i,1],d[i,2]-1]:=1;
137 end;
138 if e[d[i,1],d[i,2]+1]=0 then
139 begin
140 inc(av);
141 d[av,1]:=d[i,1];
142 d[av,2]:=d[i,2]+1;
143 e[d[i,1],d[i,2]+1]:=1;
144 end;
145 dfs(z+1);
146 while av>l do
147 begin
148 e[d[av,1],d[av,2]]:=0;
149 d[av,1]:=0;d[av,2]:=0;
150 dec(av);
151 end;
152 e[d[i,1],d[i,2]]:=1;
153 end;
154 end;
155 begin
156 hashstartup;
157 tot:=0;head:=0;ans:=0;av:=0;
158 randomize;
159 fillchar(e,sizeof(e),0);
160 for i:=0 to 6 do
161 begin
162 e[i,0]:=1;e[0,i]:=1;
163 e[i,6]:=1;e[6,i]:=1;
164 end;
165 for i:=1 to 5 do
166 begin
167 for j:=1 to 5 do
168 begin
169 read(ch);
170 case upcase(ch) of
171 ‘H‘:a[i,j]:=0;
172 ‘J‘:a[i,j]:=1;
173 end;
174 end;
175 readln;
176 end;
177 for i:=1 to 5 do
178 for j:=1 to 5 do
179 begin
180 av:=0;
181 c[1,1]:=i;c[1,2]:=j;
182 if e[i-1,j]=0 then
183 begin
184 inc(av);
185 d[av,1]:=i-1;d[av,2]:=j;
186 e[i-1,j]:=1;
187 end;
188 if e[i+1,j]=0 then
189 begin
190 inc(av);
191 d[av,1]:=i+1;d[av,2]:=j;
192 e[i+1,j]:=1;
193 end;
194 if e[i,j-1]=0 then
195 begin
196 inc(av);
197 d[av,1]:=i;d[av,2]:=j-1;
198 e[i,j-1]:=1;
199 end;
200 if e[i,j+1]=0 then
201 begin
202 inc(av);
203 d[av,1]:=i;d[av,2]:=j+1;
204 e[i,j+1]:=1;
205 end;
206 e[i,j]:=2;
207 dfs(2);
208 while av>0 do
209 begin
210 e[d[av,1],d[av,2]]:=0;
211 d[av,1]:=0;d[av,2]:=0;
212 dec(av);
213 end;
214 e[i,j]:=0;
215 end;
216 writeln(ans);
217 readln;
218 end.
于是我很嗨皮的交了一下,结果是(上面的那个是这种新的算法,下面的是之前的纯暴力)
于是我再一次有了一种彻底被吓尿的赶脚QAQ,实在没想到这玩意常数会这么大,还有后来查了一下数据,事实证明在有些比较单调的图中,我程序的速度相当坑TT
所以只能优化啦——比如,我们不难发现每个块总有一个x值最小的点,于是可以在下面的搜索过程中限制扩张方向,只准向下、向右、向左(注意:不可以一一个点为基准,同时限制向下和向左,想想为什么^_^);还有,当当前的块里面已经出现4个H的时候,我觉得这个块就没任何继续下去的必要了对不——就算接下来全是J也没有用^_^;还有就是简单的常数优化了
于是再交了一次,结果如下(这两个都是优化过的,唯一的区别在于是否在过程和函数后面加了inline;)
于是,我终于战胜了原来的纯暴力,可实际上也不难发现一个问题——我后来写的优化程序有7KB还多,而简单的暴力只有2.5KB的样子,而且弄来弄去我最终的程序也才快了0.2s的样子,在考场上这根本不存在决定性作用。
显然,对这道题而言,还是朴素的暴力算法性价比高得多,尤其是考场上在极为有限的时间内,选择一个合适的方法尤其重要;不过我们还是不要为此导致不敢乱搞,脑洞还是要大开的^_^
优化代码:
1 /**************************************************************
2 Problem: 1675
3 User: HansBug
4 Language: Pascal
5 Result: Accepted
6 Time:1660 ms
7 Memory:2972 kb
8 ****************************************************************/
9
10 const p=314159;q=951413;
11 type
12 pair=record
13 a0,b0:int64;
14 end;
15 var
16 i,j,k,l,m,n,head,tot,ans,av:longint;
17 lef,rig,fix:array[0..100000] of longint;
18 b:array[0..100000,1..2] of int64;
19 c,d:array[0..100,1..2] of longint;
20 a,e:array[0..10,0..10] of longint;
21 list:array[0..25,1..2] of int64;
22 ch:char;
23 procedure rt(var x:longint);inline;
24 var l,f:longint;
25 begin
26 if (x=0) or (lef[x]=0) then exit;
27 f:=x;l:=lef[x];
28 lef[f]:=rig[l];
29 rig[l]:=f;
30 x:=l;
31 end;
32 procedure lt(var x:longint);inline;
33 var r,f:longint;
34 begin
35 if (x=0) or (rig[x]=0) then exit;
36 f:=x;r:=rig[x];
37 rig[f]:=lef[r];
38 lef[r]:=f;
39 x:=r;
40 end;
41 function ins(var x:longint;y:longint):boolean;inline;
42 begin
43 ins:=true;
44 if x=0 then
45 begin
46 x:=y;
47 exit;
48 end;
49 if (b[y,1]<b[x,1]) or ((b[y,1]=b[x,1]) and (b[y,2]<b[x,2])) then
50 begin
51 if lef[x]=0 then lef[x]:=y else ins:=ins(lef[x],y);
52 if fix[lef[x]]<fix[x] then rt(x);
53 end
54 else if (b[y,1]>b[x,1]) or ((b[y,1]=b[x,1]) and (b[y,2]>b[x,2])) then
55 begin
56 if rig[x]=0 then rig[x]:=y else ins:=ins(rig[x],y);
57 if fix[rig[x]]<fix[x] then lt(x);
58 end
59 else exit(false);
60 end;
61 function checkhash(t:pair):boolean;inline;
62 begin
63 inc(tot);
64 b[tot,1]:=t.a0;b[tot,2]:=t.b0;
65 lef[tot]:=0;rig[tot]:=0;fix[tot]:=random(maxlongint);
66 checkhash:=ins(head,tot);
67 if not(checkhash) then dec(tot);
68 end;
69 function trans(x,y:longint):longint;inline;
70 begin
71 trans:=(x-1)*5+y;
72 end;
73 function hashstate:pair;inline;
74 var
75 i,j:longint;x,y:int64;t:pair;
76 begin
77 x:=0;y:=0;
78 for i:=1 to 7 do
79 begin
80 j:=trans(c[i,1],c[i,2]);
81 x:=(x+list[j,1]) mod q;
82 y:=(y+list[j,2]) mod p;
83 end;
84 t.a0:=x;t.b0:=y;
85 exit(t);
86 end;
87 procedure hashstartup;inline;
88 var i:longint;
89 begin
90 list[0,1]:=1;list[0,2]:=1;
91 for i:=1 to 25 do
92 begin
93 list[i,1]:=(list[i-1,1]*p) mod q;
94 list[i,2]:=(list[i-1,2]*q) mod p;
95 end;
96 end;
97 procedure dfs(z,t:longint);inline;
98 var i,j,k,l:longint;
99 begin
100 if (z-t)>4 then exit;
101 if z>7 then
102 begin
103 if checkhash(hashstate) then
104 begin
105 inc(ans);
106 end;
107 exit;
108 end;
109 l:=av;
110 for i:=1 to l do
111 begin
112 if e[d[i,1],d[i,2]]<>1 then continue;
113 c[z,1]:=d[i,1];c[z,2]:=d[i,2];
114 e[d[i,1],d[i,2]]:=2;
115 if e[d[i,1]-1,d[i,2]]=0 then
116 begin
117 inc(av);
118 d[av,1]:=d[i,1]-1;
119 d[av,2]:=d[i,2];
120 e[d[i,1]-1,d[i,2]]:=1;
121 end;
122 if e[d[i,1]+1,d[i,2]]=0 then
123 begin
124 inc(av);
125 d[av,1]:=d[i,1]+1;
126 d[av,2]:=d[i,2];
127 e[d[i,1]+1,d[i,2]]:=1;
128 end;
129 if e[d[i,1],d[i,2]-1]=0 then
130 begin
131 inc(av);
132 d[av,1]:=d[i,1];
133 d[av,2]:=d[i,2]-1;
134 e[d[i,1],d[i,2]-1]:=1;
135 end;
136 if e[d[i,1],d[i,2]+1]=0 then
137 begin
138 inc(av);
139 d[av,1]:=d[i,1];
140 d[av,2]:=d[i,2]+1;
141 e[d[i,1],d[i,2]+1]:=1;
142 end;
143 dfs(z+1,t+a[d[i,1],d[i,2]]);
144 while av>l do
145 begin
146 e[d[av,1],d[av,2]]:=0;
147 d[av,1]:=0;d[av,2]:=0;
148 dec(av);
149 end;
150 e[d[i,1],d[i,2]]:=1;
151 end;
152 end;
153 begin
154 hashstartup;
155 tot:=0;head:=0;ans:=0;av:=0;
156 randomize;
157 fillchar(e,sizeof(e),0);
158 for i:=0 to 6 do
159 begin
160 e[i,0]:=1;e[0,i]:=1;
161 e[i,6]:=1;e[6,i]:=1;
162 end;
163 for i:=1 to 5 do
164 begin
165 for j:=1 to 5 do
166 begin
167 read(ch);
168 case upcase(ch) of
169 ‘H‘:a[i,j]:=0;
170 ‘J‘:a[i,j]:=1;
171 end;
172 end;
173 readln;
174 end;
175 for i:=1 to 5 do
176 begin
177 for j:=1 to 5 do c[i-1,j]:=1;
178 for j:=1 to 5 do
179 begin
180 av:=0;
181 c[1,1]:=i;c[1,2]:=j;
182 if e[i-1,j]=0 then
183 begin
184 inc(av);
185 d[av,1]:=i-1;d[av,2]:=j;
186 e[i-1,j]:=1;
187 end;
188 if e[i+1,j]=0 then
189 begin
190 inc(av);
191 d[av,1]:=i+1;d[av,2]:=j;
192 e[i+1,j]:=1;
193 end;
194 if e[i,j-1]=0 then
195 begin
196 inc(av);
197 d[av,1]:=i;d[av,2]:=j-1;
198 e[i,j-1]:=1;
199 end;
200 if e[i,j+1]=0 then
201 begin
202 inc(av);
203 d[av,1]:=i;d[av,2]:=j+1;
204 e[i,j+1]:=1;
205 end;
206 e[i,j]:=2;
207 dfs(2,a[i,j]);
208 while av>0 do
209 begin
210 e[d[av,1],d[av,2]]:=0;
211 d[av,1]:=0;d[av,2]:=0;
212 dec(av);
213 end;
214 e[i,j]:=0;
215 end;
216 end;
217 writeln(ans);
218 readln;
219 end.