专栏文章
题解:CF342D Xenia and Dominoes
CF342D题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mio8p79u
- 此快照首次捕获于
- 2025/12/02 15:11 3 个月前
- 此快照最后确认于
- 2025/12/02 15:11 3 个月前
显然做法是计数 dp。
把
O 视作障碍,设 O 的坐标为 ,若 均无障碍且没有出界则可以放置一个可滑动的多米诺,其他方向亦然。然后我们枚举哪些位置放这样的多米诺,等价于令这两个位置为障碍然后 dp 求答案即可。但这样会算重,但只有四个方向,所以可以直接暴力容斥算。
再想如何 dp。注意到行数很少,且一个多米诺顶多管两列,我们考虑按列 dp。第 列多米诺的放置情况取决于 列的放置情况,所以需要状态压缩记录第 列的多米诺放置情况。
先考虑没有障碍的情况。设当前 dp 到第 列。多米诺可以横着放,要求 对应的状态为未填 ;也可以竖着放,要求 为已填,因为多米诺只能管两列。一共 行,所以状态为 ,可以想到状态 可以从前一列的 转移过来,对应的放置情况为全部横着放。若第 列存在竖着放的情况,也就是状态为 或 时,还可以从状态 转移过来;状态为 时还可以从状态 转移过来。
考虑存在障碍的情况。我们先算出第 列的障碍情况 。如果 存在障碍的话,我们在第 列 dp 时要把这个位置当作没有放多米诺,因为 必须放;但是在第 列 dp 时要把这个位置当作已经放了多米诺,因为这个位置不能填。然后枚举第 列多米诺放置情况 ,若 显然是不合法的。而对于下一列来说,其实际状态为 。
所以有 。还有一些上述提到的特殊转移特判一下就可以了。
容斥是 ,状压是 ,因此复杂度是 ,其中 。
代码:
CPP#include<bits/stdc++.h>
using namespace std;
#define N 10005
#define M 10
#define int long long
const int mod = 1e9+7;
int n=3,m,i,j,ans,x,y,L,R,U,D,f[N][M];
char mp[M][N];
int dp(){
memset(f,0,sizeof(f));
f[0][7]=1;
for(int i=1;i<=m;i++){
int s=0;
for(int j=1;j<=n;j++){
if(mp[j][i]=='X') s^=(1<<(j-1));
}
for(int j=0;j<=7;j++){
if(s&j) continue;
int ns=(j^s);
f[i][ns]=(f[i][ns]+f[i-1][7-j])%mod;
if(j==3 || j==6) f[i][ns]=(f[i][ns]+f[i-1][7])%mod;
if(j==7) f[i][ns]=(f[i][ns]+f[i-1][3]+f[i-1][6])%mod;
}
}
return f[m][7];
}
signed main(){
scanf("%lld",&m);
for(i=1;i<=n;i++) scanf("%s",mp[i]+1);
for(i=1;i<=n;i++){
for(j=1;j<=m;j++) if(mp[i][j]=='O') x=i,y=j;
}
mp[x][y]='X';
for(L=0;L<=1;L++){
if(L && (y<3 || mp[x][y-1]=='X' || mp[x][y-2]=='X')) continue;
for(R=0;R<=1;R++){
if(R && (y>m-2 || mp[x][y+1]=='X' || mp[x][y+2]=='X')) continue;
for(U=0;U<=1;U++){
if(U && (x<3 || mp[x-1][y]=='X' || mp[x-2][y]=='X')) continue;
for(D=0;D<=1;D++){
if(D && (x>1 || mp[x][y+1]=='X' || mp[x][y+2]=='X')) continue;
if(!L && !R && !U && !D) continue;
if(L) mp[x][y-1]='X',mp[x][y-2]='X';
if(R) mp[x][y+1]='X',mp[x][y+2]='X';
if(U) mp[x-1][y]='X',mp[x-2][y]='X';
if(D) mp[x+1][y]='X',mp[x+2][y]='X';
int res=dp();
if((L+R+U+D)&1) ans=(ans+res)%mod;
else ans=(ans-res+mod)%mod;
if(L) mp[x][y-1]='.',mp[x][y-2]='.';
if(R) mp[x][y+1]='.',mp[x][y+2]='.';
if(U) mp[x-1][y]='.',mp[x-2][y]='.';
if(D) mp[x+1][y]='.',mp[x+2][y]='.';
}
}
}
}
printf("%lld\n",ans);
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...