[SGU 223][bsoj2772] little kings


题目描述

在n*n(1<=n<=10)的棋盘上放k(0<=k<=n*n)个国王(可攻击相邻的8 个格子),求使它们无法互相攻击的方案总数。


输入格式

输入文件仅一行为两个整数n和k。


输出格式

输出文件仅一行为方案总数,若不能够放置则输出0。


样例数据

样例输入

样例数据#1
3 2
样例数据#2
4 4

样例输出

样例数据#1
16
样例数据#2
79


题目分析

状压裸题,先做poj2411
不过有国王个数限制,要把国王个数写入状态。


源代码

#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
    int num=0,bj=1;
    char x=getchar();
    while(x<'0'||x>'9') {
        if(x=='-')bj=-1;
        x=getchar();
    }
    while(x>='0'&&x<='9') {
        num=num*10+x-'0';
        x=getchar();
    }
    return num*bj;
}
long long cnt=0,ans=0,f[15][1105][205];
int n,King,State[1105],king[1105];
bool Check(int a,int b) { //检查状态State[a]与State[b]是否冲突
    return !(State[a]&State[b])&&!(State[a]&(State[b])<<1)&&!(State[a]&(State[b])>>1); //上一排的左右3格都不能有国王
}
int main() {
    scanf("%d%d",&n,&King);
    for(int i=0; i<(1<<n); i++) { //枚举每行状态初始化
        if(i&(i<<1))continue; //左右冲突
        cnt++;
        State[cnt]=i; //保存状态
        for(int j=0; j<n; j++)
            if(i&(1<<j))king[cnt]++; //统计国王个数
    }
    f[0][1][0]=1; //初始条件:第0行全为0
    for(int i=1; i<=n; i++) //阶段:行
        for(int j=1; j<=cnt; j++) //枚举状态
            for(int k=0; k<=King; k++) //枚举国王数
                if(k>=king[j])
                    for(int t=1; t<=cnt; t++) //枚举i-1行状态
                        if(Check(j,t))f[i][j][k]+=f[i-1][t][k-king[j]];
    for(int i=1; i<=cnt; i++)ans+=f[n][i][King];
    printf("%lld\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值