1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区(题解第二弹)

1675: [Usaco2005 Feb]Rigging the Bovine Election 竞选划区

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 198  Solved: 118
[Submit][Status][Discuss]

Description

It's election time. The farm is partitioned into a 5x5 grid of cow locations, each of which holds either a Holstein ('H') or Jersey ('J') cow. The Jerseys want to create a voting district of 7 contiguous (vertically or horizontally) cow locations such that the Jerseys outnumber the Holsteins. How many ways can this be done for the supplied grid?

 农场被划分为5x5的格子,每个格子中都有一头奶牛,并且只有荷斯坦(标记为H)和杰尔西(标记为J)两个品种.如果一头奶牛在另一头上下左右四个格子中的任一格里,我们说它们相连.    奶牛要大选了.现在有一只杰尔西奶牛们想选择7头相连的奶牛,划成一个竞选区,使得其中它们品种的奶牛比荷斯坦的多.  要求你编写一个程序求出方案总数.

Input

* Lines 1..5: Each of the five lines contains five characters per line, each 'H' or 'J'. No spaces are present.

    5行,输入农场的情况.

Output

* Line 1: The number of distinct districts of 7 connected cows such that the Jerseys outnumber the Holsteins in the district.

    输出划区方案总数.

 

Sample Input

HHHHH
JHJHJ
HHHHH
HJHHJ
HHHHH

Sample Output

2

HINT

 


 

 

Source

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.  

 

posted @ 2015-04-10 12:00  HansBug  阅读(654)  评论(0编辑  收藏  举报