2 条题解

  • 0
    @ 2026-5-7 18:58:39
    #include <stdio.h>
    #define MAXL 6
    #define MAXH 6
    #define MAXN (MAXL/2)*(MAXL/2)
    
    char view[MAXH][2][MAXL+1];
    int supp[MAXH+1][10000],nb[MAXH+1];
    long long cnt, np[MAXH+1][10000];
    int H, pos[MAXN];
    int map[MAXL][MAXL];
    
    void MLX(int h, int nr, int lastx, int lasty) {
      int x, y, i,j,k,q,deg;
      char c[MAXN];
      for(x=lastx;x<MAXL-1;x++) {
          for(y=(x==lastx)?lasty+1:0;y<MAXL-1;y++) {
              if(map[x][y]==-1 && map[x][y+1]==-1) {
                pos[nr]=x*(MAXL-1)+y;
                map[x][y]=map[x+1][y]=map[x][y+1]=map[x+1][y+1]=nr;
                MLX(h,nr+1,x,y);
                map[x][y]=map[x+1][y]=map[x][y+1]=map[x+1][y+1]=-1;
              }
            }
      }
      //Is this configuration consistent with indata?
      for(i=0;i<nr;i++) c[i]='-';
      for(i=0;i<2;i++) {
        for(j=0;j<MAXL;j++) {
          q=-1;
          for(k=0;k<MAXL;k++) {
            if(i==0) { x=j; y=k;}
            if(i==1) { y=j; x=MAXL-1-k;}
            if(i==2) { x=MAXL-1-j; y=MAXL-1-k;}
            if(i==3) { y=MAXL-1-j; x=k;}
            if(map[x][y]!=-1) {
              q=map[x][y];
              break;
            }
          }
          if(q==-1 && view[h][i][j]!='.') return;
          if(q!=-1) {
            if(view[h][i][j]=='.') return;
            if(c[q]=='-') c[q]=view[h][i][j];
            if(c[q]!=view[h][i][j]) return;
          }
        }
      }
      //Is there any hidden pieces that can have any color?
      deg=1;
      for(i=0;i<nr;i++) if(c[i]=='-') deg*=3;
    
      //print();
      //Sum over possibilities
      np[h+1][nb[h+1]]=0;
      for(i=0;i<nb[h];i++) {
        for(j=0;j<nr;j++) if(((supp[h][i] >> pos[j]) & 1) == 0) break;
        if(j==nr) {
          np[h+1][nb[h+1]]+=np[h][i]*deg;
          cnt+=np[h][i]*deg;
        }
      }
      //Calculate its support for next layer
      if(np[h+1][nb[h+1]]>0) {
        supp[h+1][nb[h+1]]=0;
        for(x=0;x<MAXL-1;x++) for(y=0;y<MAXL-1;y++) {
            q=x*(MAXL-1)+y;
            if(map[x][y]!=-1 || map[x][y+1]!=-1 || map[x+1][y]!=-1 || map[x+1][y+1]!=-1) {
              supp[h+1][nb[h+1]]|=(1<<q);
            }
          }
        nb[h+1]++;
      }
    }
    
    
    int main() {
      //freopen("lego.in", "rt", stdin);
      //freopen("lego.out", "wt", stdout);
      int i,j,h;
      scanf("%d",&H);
      for(i=0;i<2;i++) for(h=H-1;h>=0;h--) {
          scanf("%s", view[h][i]);
        }
      nb[0]=1;
      np[0][0]=1;
      supp[0][0]=~0; //Full support
      for(h=0;h<H;h++) {
        cnt=0;
        for(i=0;i<MAXL;i++) for(j=0;j<MAXL;j++) map[i][j]=-1;
        MLX(h,0,-1,-1);
      }
      printf("%lld\n", cnt);
      return 0;
    }
    
    • 0
      @ 2026-5-7 18:57:59

      从下午 17:00 调到了 23:30,呜呜呜(写篇题解纪念一下~


      分析题目,主要有两个限制:颜色限制和不能悬空。

      我们首先考虑颜色的限制。

      所有方块都是 2×2×12 \times 2 \times 1 的,所以一个方块只会对一个层影响

      因此,不妨先找到每一层的所有放置方案。

      具体地,在某一层上,我们以方块的左上角位置表示这个 2×2×12 \times 2 \times 1 的方块。显然,一共有 2525 个可能的左上角。

      我们可以使用一次 dfs 求解出所有可能的方块放置方案(不考虑颜色)。

      具体而言,就是进行 dfs,每一次有 25+125 + 1 种选择(不放或放在某一位置),但不能重叠。

      代码实际跑下来,总共只有 64276427 种方案,可以被接受。

      因此,我们可以得到一个数组 allall,表示所有 64276427 中放置方案。


      接下来,我们对于每一层,找到所有合法的放置方案。

      具体地,我们可以枚举每一层,然后枚举 allall 中的每一种方案。

      对于一种方案,我们从两个视角分别枚举出最靠前的方块,并把其涂上对应颜色。

      如果颜色重复,则需判无解。如果有可以随意涂色的方块(设为 xx 个),则贡献为 3x3^x,存下来即可。

      实现的时候,我们可以使用 (x1)×6+y(x - 1) \times 6 + y 表示 (x,y)(x, y),这样就把每个格子标上了 1361 \sim 36

      然后,对于合法方案,可以使用一个 3636 位二进制数存储每个位置是否有方块

      注意,这里只需要记录是否存在方块,因为不确定颜色的已经存储贡献 3x3^x

      经过上述操作,我们可以得到 HH 个数组 cengiceng_i,表示每一层的可能放置方案。

      对于 cengiceng_i 中的每一个元素,我们需要记录的是方块摆放情况和权值(形如 3x3^x)。


      颜色限制已经解决(我们得到了每一层的可能放置方案),考虑不能悬空。

      此时就需要动态规划计算了,是本题的核心。

      我们用 dpi,sdp_{i, s} 表示到第 ii 层为止,顶层方块摆放情况为 ss 的方案数。

      转移的时候,我们枚举上层的所有 2×22 \times 2 方块,然后判断下面有没有方块托住即可。

      具体地,下层放置情况 ss' 是一个 3636 位二进制数,表示某个位置是否存在方块(颜色已经不重要了)。

      这样,就可以完成转移了。

      特别的,3636 位二进制一共有 2362^{36} 个,但实际上有用的很少。因此,我们可以使用 map 存 dp 数组,转移的时候枚举数组中非 00 的位置即可。


      代码就不放了,因为写得太难看了(/kk。

      建议写的时候多开函数方便调试,因为我写了 4.27k 调了 6.5h。

      复杂度挺玄学的,但跑得不慢,最大 329ms:

      求赞 qwq~

      • 1

      信息

      ID
      3623
      时间
      1000ms
      内存
      64MiB
      难度
      10
      标签
      递交数
      1
      已通过
      1
      上传者