zoukankan      html  css  js  c++  java
  • 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

    题解:之前的题解中(传送门),采用的是(Oleft({25}^{7} ight))的简单暴力枚举,虽然能A,我一直认为还有更灵活的办法可以去做,于是有了这个第二篇题解

    这次的思路是:每次先找一个点,然后向这个点的四周进行扩张,每一层dfs在原有的块的基础上再向外扩张一个,最终形成的块必然是7个连续的格子,应该能够起到比较好的优化效果——因为我每次选取扩张的点,都是通过动态维护当前块周围一圈的点来进行的,对于联通块而言,在地图内最多只能有15个周围的点,所以复杂度一下子降到了(Oleft({15}^{7} ight)),并且完全不需要判断7个点是否构成一块。。。

    以上是优点,但是这样一来仔细想想,缺点也十分明显——由于对于同样一个图形而言,可以由很多中扩张顺序可以形成,所以势必造成巨大的重复计算,这是个致命的伤。。。所以只好进行判重,所以只好又写了个双值哈希,确保一种选取情况对应一对唯一的哈希值,而对于一大堆乱七八糟的哈希值对,怎样判断是否存在呢?于是逗比的我又来个了平衡树进行查找,这样子算下来,时间复杂度 (Oleft({15}^{7} imes 7 Ans log Ans ight))

      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.  
  • 相关阅读:
    具体解释协方差与协方差矩阵
    百度地图SDK for Android v2.1.3全新发布
    奇妙的等式
    Canny边缘检测及C++实现
    移动火柴问题
    移动火柴问题
    奇妙的等式 && 精妙的证明(二)
    奇妙的等式 && 精妙的证明(二)
    拉马努金恒等式
    拉马努金恒等式
  • 原文地址:https://www.cnblogs.com/HansBug/p/4414164.html
Copyright © 2011-2022 走看看