欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BZOJ2669

程序员文章站 2024-01-12 09:29:28
...

来自蒟蒻XXJ的做题记录

观察一下就知道里面最多会有8个X嘛== 然后就状压一下啊……

\(f[i][j]=f[i-1][j]*(cnt[s]-i+1)+f[i-1][j-(1<<p)]\)

PS:cnt[s] 表示一个填好的状态s下有多少个地方可以放数字i

来自dalao PoPoQQQ:

原来只考虑了保证标记的位置都是局部最小值

但是问题是这样虽然保证了标记的位置都是局部最小值,但是可能会导致一些未标记的位置成为局部极小值,因此我们枚举其他可以成为局部极小值的位置,容斥一下即可

所以正解是枚举每一种可能的局部最小值分布,用状压dp求出方案数,然后容斥(一步减,两步加)

#include<bits/stdc++.h>
using namespace std;
const int MOD=12345678;
int n,m,x[9],y[9],top,cnt[1<<9];
long long f[30][1<<9];
long long ans;
bool mm[6][9],wtm[6][9];
int dx[]={0,1,0,-1,1,-1,1,-1};
int dy[]={1,0,-1,0,1,-1,-1,1};
int dp(){
    top=0;int s;memset(cnt,0,sizeof(cnt));
    memset(f,0,sizeof(f));
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            if(mm[i][j]){
                x[++top]=i;y[top]=j;
            }
    s=1<<top;
    for(int i=0;i<s;i++){
        memset(wtm,0,sizeof(wtm));
        for(int j=0;j<top;j++){
            if(!((1<<j)&i)){
                for(int k=0;k<8;k++){
                    int xx=x[j+1]+dx[k];
                    int yy=y[j+1]+dy[k];
                    if(xx<0||yy<0||xx>=n||yy>=m) continue;
                    wtm[xx][yy]=1;
                }
                wtm[x[j+1]][y[j+1]]=1;
            }
        }
        for(int ni=0;ni<n;ni++)
            for(int nj=0;nj<m;nj++) cnt[i]+=!(wtm[ni][nj]);
    }
    f[0][0]=1;
    for(int i=1;i<=n*m;i++)
        for(int j=0;j<s;j++){
            f[i][j]+=(f[i-1][j]*(cnt[j]-i+1))%MOD;
            f[i][j]%=MOD;
            for(int p=0;p<top;p++){
                if(!((1<<p)&j)) continue;
                f[i][j]+=f[i-1][j-(1<<p)];
                f[i][j]%=MOD;
            }
        }
    return f[n*m][s-1];
}
void dfs(int nx,int ny,int z){
    if(ny==m){dfs(nx+1,0,z);return;}
    if(nx==n){
        ans+=dp()*z;
        ans%=MOD;
        return;
    }//Judge that the spot can be X or not Just Judge its round
    dfs(nx,ny+1,z);
    int judge(1);
    for(int i=0;i<8;i++){
        int xx=nx+dx[i];
        int yy=ny+dy[i];
        if(xx<0||yy<0||xx>=n||yy>=m) continue;
        if(mm[xx][yy]) {judge=0;break;}
    }
    if(mm[nx][ny]) judge=0;
    if(judge){mm[nx][ny]=1;dfs(nx,ny+1,z*(-1));mm[nx][ny]=0;}
}
void input(){
    cin>>n>>m;
    cin.get();
    for(int i=0;i<n;i++){
        char c[10];
        scanf("%s",c);
        for(int j=0;j<m;j++){
            if(c[j]=='X') mm[i][j]=1;
            else mm[i][j]=0;
        }
    }
}
void xxj(){
    dfs(0,0,1);
}
void output(){
    cout<<(ans+12*MOD)%MOD<<endl;
}

int main(){
    input();
    xxj();
    output();
    return 0;
}

推荐阅读