zoukankan      html  css  js  c++  java
  • [BZOJ2669][CQOI2012]局部最小值(容斥+状压DP)

    发现最多有8个限制位置,可以以此为基础DP和容斥。

    $f_{i,j}=f_{i-1,j} imes (cnt_j-i+1)+sum_{ksubset j} f_{i-1,k}$

    $cnt_j$表示当限制状态为j时i有多少个可行位置。

    这样DP只能保证所有题设位置全部是局部最小值,但不保证其它位置不会变成局部最小值,容斥解决。

    $O(DFS*8nm*2^8)$

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 using namespace std;
     6 
     7 const int mod=12345678;
     8 int dx[9]={0,1,0,-1,0,1,-1,1,-1},dy[9]={0,0,1,0,-1,1,-1,-1,1};
     9 int n,m,ans,l,f[30][1<<8],cnt[1<<8],vis[8][8],a[10][2];
    10 char ch[8][8];
    11 
    12 int dp(){
    13     memset(f,0,sizeof(f));
    14     memset(cnt,0,sizeof(cnt));
    15     int top=0;
    16     rep(i,1,n) rep(j,1,m) if (ch[i][j]=='X')
    17         a[++top][0]=i,a[top][1]=j;
    18     for (int S=0; S<(1<<top); S++){
    19         memset(vis,0,sizeof(vis));
    20         rep(i,1,top) if (~S&(1<<(i-1))) vis[a[i][0]][a[i][1]]=1;
    21         rep(i,1,n) rep(j,1,m){
    22             bool flag=0;
    23             rep(l,0,8) if (vis[i+dx[l]][j+dy[l]]) { flag=1; break; }
    24             if (!flag) cnt[S]++;
    25         }
    26     }
    27     f[0][0]=1;
    28     rep(i,1,n*m) for (int j=0; j<(1<<top); j++){
    29         f[i][j]=(f[i][j]+1ll*f[i-1][j]*max(cnt[j]-i+1,0))%mod;
    30         rep(k,1,top) if (j&(1<<(k-1)))
    31             f[i][j]=(f[i][j]+f[i-1][j^(1<<(k-1))])%mod;
    32     }
    33     return f[n*m][(1<<top)-1];
    34 }
    35 
    36 void dfs(int x,int y,int t){
    37     if (y==m+1){ dfs(x+1,1,t); return; }
    38     if (x==n+1){ ans=(ans+dp()*(t&1?-1:1))%mod; return; }
    39     dfs(x,y+1,t);
    40     bool flag=0;
    41     rep(i,0,8) if (ch[x+dx[i]][y+dy[i]]=='X') { flag=1; break; }
    42     if (!flag) ch[x][y]='X',dfs(x,y+1,t+1),ch[x][y]='.';
    43 }
    44 
    45 int main(){
    46     freopen("bzoj2669.in","r",stdin);
    47     freopen("bzoj2669.out","w",stdout);
    48     scanf("%d%d",&n,&m);
    49     rep(i,1,n) scanf("%s",ch[i]+1);
    50     rep(i,1,n) rep(j,1,m) if (ch[i][j]=='X')
    51         rep(k,1,8) if (ch[i+dx[k]][j+dy[k]]=='X') { puts("0"); return 0; }
    52     dfs(1,1,0); printf("%d
    ",(ans+mod)%mod);
    53     return 0;
    54 }
  • 相关阅读:
    ML-线性回归
    ML-决策树
    numpy常用知识点备忘(2)
    numpy常用知识点备忘
    ML-朴素贝叶斯算法
    Git常用命令备忘
    机器学习-决策树算法
    机器学习-线性模型(线性回归与逻辑回归)
    深入JVM内核(四)垃圾回收器与GC参数
    深入JVM内核(三)对象存活判定算法与垃圾收集算法
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9602109.html
Copyright © 2011-2022 走看看