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
    

    Solution:

      本题状压dp水题

      预处理单行合法的状态和所放国王数,定义$f[i][j][k]$表示前$i$行放了$j$个国王且最后一行状态为$k$时的方案数。

      那么转移就比较简单了,一层枚举阶段j(国王数),第二层枚举阶段i(行数),第三层枚举状态k(最后一行国王状态),第四层枚举决策p(转移后状态),判断合法后随便搞搞就好了。

    代码:

    /*Code by 520 -- 10.14*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=10;
    int n,m,lim,w[1<<N];
    ll f[N][N*N*2][1<<N],ans;
    bool sta[1<<N];
    
    int main(){
        ios::sync_with_stdio(0);
        cin>>n>>m,lim=(1<<n)-1;
        For(i,0,lim) {
            sta[i]=(!(i&(i<<1))&&!(i&(i>>1)));
            if(sta[i])
                For(j,0,n-1) if(i&(1<<j)) w[i]++;
        }
        f[0][0][0]=1;
        For(p,0,m) For(i,1,n) For(j,0,lim)
            if(sta[j]) For(k,0,lim) 
                if(sta[k]&&!(j&k)&&!((j<<1)&k)&&!((j>>1)&k))
                    f[i][p+w[j]][j]+=f[i-1][p][k];
        For(i,0,lim) ans+=f[n][m][i];
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Ubuntu 18.04安装gcc、g++ 4.8
    Java 接口返回值集合防止空指针
    Linux CentOS7.9环境下搭建Java Web 环境
    Springboot集成UReport2
    linux 环境中 单独执行 python 脚本
    sql 注入的问题
    检验上传文件的大小
    Gunicorn使用讲解
    CentOS下安装部署对象存储服务MinIO
    阿里云CentOS7安装MySQL
  • 原文地址:https://www.cnblogs.com/five20/p/9852742.html
Copyright © 2011-2022 走看看