2 条题解
-
0
#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
从下午 17:00 调到了 23:30,呜呜呜(写篇题解纪念一下~
分析题目,主要有两个限制:颜色限制和不能悬空。
我们首先考虑颜色的限制。
所有方块都是 的,所以一个方块只会对一个层影响。
因此,不妨先找到每一层的所有放置方案。
具体地,在某一层上,我们以方块的左上角位置表示这个 的方块。显然,一共有 个可能的左上角。
我们可以使用一次 dfs 求解出所有可能的方块放置方案(不考虑颜色)。
具体而言,就是进行 dfs,每一次有 种选择(不放或放在某一位置),但不能重叠。
代码实际跑下来,总共只有 种方案,可以被接受。
因此,我们可以得到一个数组 ,表示所有 中放置方案。
接下来,我们对于每一层,找到所有合法的放置方案。
具体地,我们可以枚举每一层,然后枚举 中的每一种方案。
对于一种方案,我们从两个视角分别枚举出最靠前的方块,并把其涂上对应颜色。
如果颜色重复,则需判无解。如果有可以随意涂色的方块(设为 个),则贡献为 ,存下来即可。
实现的时候,我们可以使用 表示 ,这样就把每个格子标上了 。
然后,对于合法方案,可以使用一个 位二进制数存储每个位置是否有方块。
注意,这里只需要记录是否存在方块,因为不确定颜色的已经存储贡献 。
经过上述操作,我们可以得到 个数组 ,表示每一层的可能放置方案。
对于 中的每一个元素,我们需要记录的是方块摆放情况和权值(形如 )。
颜色限制已经解决(我们得到了每一层的可能放置方案),考虑不能悬空。
此时就需要动态规划计算了,是本题的核心。
我们用 表示到第 层为止,顶层方块摆放情况为 的方案数。
转移的时候,我们枚举上层的所有 方块,然后判断下面有没有方块托住即可。
具体地,下层放置情况 是一个 位二进制数,表示某个位置是否存在方块(颜色已经不重要了)。
这样,就可以完成转移了。
特别的, 位二进制一共有 个,但实际上有用的很少。因此,我们可以使用
map存 dp 数组,转移的时候枚举数组中非 的位置即可。
代码就不放了,因为写得太难看了(/kk。
建议写的时候多开函数方便调试,因为我写了 4.27k 调了 6.5h。
复杂度挺玄学的,但跑得不慢,最大 329ms:

求赞 qwq~
- 1
信息
- ID
- 3623
- 时间
- 1000ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者