zoukankan      html  css  js  c++  java
  • 洛谷 P1896 [SCOI2005]互不侵犯

    题目描述

    (N×N)的棋盘里面放(K)个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共(8)个格子。

    注:数据有加强((2018/4/25))

    输入输出格式

    输入格式:

    只有一行,包含两个数(N,K ( 1 <=N <=9, 0 <= K <= N * N))

    输出格式:

    所得的方案数

    输入输出样例

    输入样例#1:

    3 2
    

    输出样例#1:

    16
    

    思路:见代码注释。

    代码:

    /*f[i][j][k]表示第i行,状态为j,前面摆了k个国王时方案数*/
    #include<cstdio>
    #define ll long long
    ll n,k,king[513],f[10][513][82],num,state[513],ans;
    //state是当前状态,king是当前状态的国王数
    int main() {
      scanf("%d%d",&n,&k);
      int maxn=1<<n;
      for(int i=0;i<maxn;++i) { //预处理出所有可能组成的状态
        if(!(i&(i<<1))) {
          state[++num]=i;
          int res=i;
          while(res) {
            if(res&1) ++king[num];   //记录这个状态下国王的个数
            res>>=1;
          }
        }
      }
      for(int i=1;i<=num;++i) 
        if(king[i]<=k) f[1][i][king[i]]=1;
      //所有状态下的国王个数不能超过k
      for(int i=2;i<=n;++i) {   //状态转移,注意判断合法,冲突即可。
        for(int j=1;j<=num;++j) {
          for(int l=1;l<=num;++l) {
            if(state[j]&state[l]) continue;
            if(state[j]&(state[l]<<1)) continue;
            if((state[j]<<1)&state[l]) continue;
            for(int s=1;s<=k;++s) {
              if(s+king[j]>k) continue;
              f[i][j][king[j]+s]+=f[i-1][l][s];
            }
          }
        }
      } 
      for(int i=1;i<=n;++i)
        for(int j=1;j<=num;++j) 
          ans+=f[i][j][k];
      printf("%lld
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    预分区
    Flume学习笔记
    1
    在视图中使用时间
    Java 正则表达式的使用
    Reactor模式(反应器模式)
    Control character in cookie value, consider BASE64 encoding your value , java操作cookie遇到中文会报错的解决方案
    关于这周工作中遇到的关于缓存问题的记录
    eclipse import的项目报autowired cannot be resolved to a type的错误
    m2e插件的新下载地址
  • 原文地址:https://www.cnblogs.com/grcyh/p/10804288.html
Copyright © 2011-2022 走看看