【洛谷 1896】互不侵犯_new

题目描述

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

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

输入格式

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

输出格式

所得的方案数

输入输出样例

输入 #1
3 2
输出 #1
16

题解:更新版本的嘻嘻。

#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
typedef long long ll;
int n,k;
ll dp[13][15002][81],sum,ans,cnt; 
ll st[787878],ki[78787];
void init(){
    scanf("%d %d",&n,&k);
    int op=(1<<n);
    for(int i=0;i<op;i++){
        if(!((i<<1)&i)){
            st[++cnt]=i;
            int mt=i;
            while(mt){
                ki[cnt]+=mt%2;
                mt>>=1;
            }
        }
    } 
}
void work(){
    for(int i=1;i<=cnt;i++)
        if(ki[i]<=k) dp[1][i][ki[i]]=1;
    for(int i=2;i<=n;i++){//枚举行数 
        for(int j=1;j<=cnt;j++){//枚举状态 
            for(int p=1;p<=cnt;p++){//枚举上一行状态
                if((st[j] & st[p])||((st[j]<<1) & st[p])||(st[j] & (st[p]<<1))) continue;
                for(int s=1;s<=k;s++){
                    if(ki[j]+s>k) continue; 
                    dp[i][j][ki[j]+s]+=dp[i-1][p][s];
                }    
            } 
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=cnt;j++)
            ans+=dp[i][j][k];
    cout<<ans; 
}
int main(){
    //freopen("1896.in","r",stdin);
    //freopen("1896.out","w",stdout);
    init(); work();
    return 0;
}
原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11328157.html