zoukankan      html  css  js  c++  java
  • 【BZOJ 2669】 2669: [cqoi2012]局部极小值 (状压DP+容斥原理)

    2669: [cqoi2012]局部极小值

    Time Limit: 3 Sec  Memory Limit: 128 MB
    Submit: 667  Solved: 350

    Description

    有一个nm列的整数矩阵,其中1到nm之间的每个整数恰好出现一次。如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点)都小,我们说这个格子是局部极小值。
    给出所有局部极小值的位置,你的任务是判断有多少个可能的矩阵。

    Input

    输入第一行包含两个整数nm(1<=n<=4, 1<=m<=7),即行数和列数。以下n行每行m个字符,其中“X”表示局部极小值,“.”表示非局部极小值。

    Output

    输出仅一行,为可能的矩阵总数除以12345678的余数。

    Sample Input

    3 2
    X.
    ..
    .X

    Sample Output

    60

    HINT

    Source

    【分析】

      我好蠢啊。。。

      保证每个数各不相同,又有大小关系,那么、、数字从小到大填。

      其实局部极小值<=8的,这个可以状压,$f[i][j]$表示填了前i个数,局部极小值被填的状态是j的方案数。

      有:

      $f[i][j]=f[i-1][j]*(p[j]-i+1)+f[i-1][j-(1<<X)]$

      但是,还要保证一点是非极小值一定非极小,上面没有保证,

      所以枚举哪些非极小弄成了极小,容斥算出正确答案即可。

      复杂度?$O(dfs*n*m*8*2^8)$大概是这样吧。。数据很小嘛。。。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 #define Mod 12345678
      8 #define LL long long
      9 
     10 int a[5][8],num[5][8],p[310];
     11 int n,m;
     12 int bx[10]={0,1,0,-1,0,1,-1,1,-1},
     13     by[10]={0,0,1,0,-1,1,-1,-1,1};
     14 char s[10];
     15 bool vis[5][8];
     16 LL f[30][310],ans=0;
     17 
     18 LL get_ans()
     19 {
     20     int cnt=0;
     21     for(int i=1;i<=n;i++)
     22      for(int j=1;j<=m;j++) if(a[i][j]==1) num[i][j]=++cnt;
     23     for(int k=0;k<=(1<<cnt)-1;k++)
     24     {
     25         for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) vis[i][j]=1;
     26         for(int i=1;i<=n;i++)
     27          for(int j=1;j<=m;j++) if(a[i][j]==1&&((1<<num[i][j]-1)&k)==0)
     28          {
     29              for(int l=1;l<=8;l++)
     30              {
     31                 int nx=i+bx[l],ny=j+by[l];
     32                 vis[nx][ny]=0;
     33              }
     34          }
     35         p[k]=0;
     36         for(int i=1;i<=n;i++)
     37          for(int j=1;j<=m;j++) if(vis[i][j]&&a[i][j]==0) {p[k]++;vis[i][j]=0;}
     38         for(int i=1;i<=cnt;i++) if((1<<i-1)&k) p[k]++;
     39     }
     40     memset(f,0,sizeof(f));
     41     f[0][0]=1;
     42     for(int i=1;i<=n*m;i++)
     43      for(int j=0;j<=(1<<cnt)-1;j++)
     44      {
     45          f[i][j]=f[i-1][j]*(p[j]-i+1);f[i][j]%=Mod;
     46          for(int k=1;k<=cnt;k++) if((1<<k-1)&j)
     47          {
     48              f[i][j]+=f[i-1][j-(1<<k-1)];
     49              f[i][j]%=Mod;
     50          }
     51      }
     52     return f[n*m][(1<<cnt)-1];
     53 }
     54 
     55 void dfs(int x,int y,int f)
     56 {
     57     if(y==m+1) {dfs(x+1,1,f);return;}
     58     if(x==n+1)
     59     {
     60         ans+=f*get_ans();
     61         ans=(ans%Mod+Mod)%Mod;
     62         return;
     63     }
     64     if(a[x][y]==1) {dfs(x,y+1,f);return;}
     65     bool ok=1;
     66     for(int i=1;i<=8;i++)
     67     {
     68         int nx=x+bx[i],ny=y+by[i];
     69         if(nx<1||nx>n||ny<1||ny>m) continue;
     70         if(a[nx][ny]==1) {ok=0;break;}
     71     }
     72     if(ok)
     73     {
     74         a[x][y]=1;
     75         dfs(x,y+1,-f);
     76         a[x][y]=0;
     77     }
     78     dfs(x,y+1,f);
     79 }
     80 
     81 int main()
     82 {
     83     scanf("%d%d",&n,&m);
     84     for(int i=1;i<=n;i++)
     85     {
     86         scanf("%s",s+1);
     87         for(int j=1;j<=m;j++)
     88         {
     89             if(s[j]=='X') a[i][j]=1;
     90             else a[i][j]=0;
     91         }
     92     }
     93     for(int i=1;i<=n;i++)
     94      for(int j=1;j<=m;j++) if(a[i][j]==1)
     95      {
     96          for(int k=1;k<=8;k++)
     97          {
     98              int nx=i+bx[i],ny=j+by[i];
     99              if(nx<1||nx>n||ny<1||ny>m) continue;
    100              if(a[nx][ny]==1) {printf("0
    ");return 0;}
    101          }
    102      }
    103     // memset(vis,1,sizeof(vis));
    104     dfs(1,1,1);
    105     printf("%lld
    ",ans);
    106     return 0;
    107 }
    View Code

    2017-04-06 10:08:51

  • 相关阅读:
    Java 几个权限关键字
    Java变量的定义
    Hibernate反射DAO模式
    BroadcastReceiver与Notification的综合应用自定义Action的调用方式
    SEO优化技术之关键字
    中软国际助力四所高校建设国家级大学生校外实践教育基地
    讲师团队的培养
    IT与学习
    程序员,你的粮草何在?
    如何更好的学好Linux操作系统
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6672179.html
Copyright © 2011-2022 走看看