1896 [SCOI2005]互不侵犯King

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

【输入格式】输入有多组方案,每组数据只有一行为两个整数n和k。

【输出格式】每组数据一行为方案总数,若不能够放置则输出0。

【问题分析】

由问题很容易联想起经典的“八皇后”问题,似乎就是“皇后”变成了“国王”,而且格子范围似乎也差不多,所求问题也一样。那么这个问题也能用搜索解决吗?

可稍加分析可知搜索是很难胜任的,因为国王的数目可以是很大,加上它与“八皇后”问题的一个本质上的不同便是每个国王只影响周围的一个格子,所以剪枝条件也很少,指数级别的搜索是无法在时限内出解的。

那么一般的动态规划能解决吗?典型的二维DP,F[I,J]似乎无法很好地把状态表示出来,因此我们只能考虑状态压缩的动态规划。

首先我们要注意到这题的关键——每个国王只影响周围八个方向的一个格子,它虽然否定了搜索,却给状态压缩带来了无限生机!

我们改变之前动态规划的思维方式,一行一行地摆放国王,当我们摆放第I行时,这一行只会和前后一行的互相影响,而这一行的状态是可以由我们确定的。那是否可以把一行当作一个整体,然后像传统的动态规划那样进行处理呢?让我们试一下。

每一行它对下一行的影响就体现在这一行的摆放方式以及之前总共放了多少个国王。所以我们可以把摆放方式作为状态,设f[i,j,s]表示第i行状态为a[j]且前i行已放s个国王的方案总数。这样很容易便得到了一个粗略的方程:

 F[i,j,S]=∑F[i-1,k,T]

a[j],a[k]分别表示一种摆放方式,F[i,j]表示第i行用a[j]的摆放方式,且a[j]与a[k]相兼容。并且S等于T加上a[j]这种方式在这一行放置的国王数。

很明显这个方程是没有后效性的,可关键就在于j,k怎么在计算机上表示出来,这就需要我们的主题:状态压缩

看图便知,每一个格子只有两种状态,放和不放,并且注意到格子宽度最大为9。由这便想到了熟悉的二进制表示法。每一个格子对应一个二进制位。这样每一行便对应一个N位的二进制数,如下图所示:

1   0   0   0   1   0   0   0

即十进制的128+8=136

这样我们就可以把一种摆放方式转化为一个数,这样上面方程中的J,K就可以用数字来代替。我们就把一行的摆放方式作为状态,并把它压缩成了一个数!具体的算法流程如下:

①对于每一行,我们通过搜索得出一个合法状态。

②然后再枚举上一行与这一行相容的状态再累加即可,状态用N位的二进制数表示,最大仅为512,所以一个512*9*81的数组就可以了,还可以用滚动数组的技巧。空间是肯定可以承受的。

而一个粗略的时间复杂度:O(K*N*2^N*2^N),似乎大了点。不过注意到由于国王是不能相邻放置的。所以我们可以用一个f(n)来表示当列数为n时每一行可能的放置总数。则f(n)=f(n-1)+f(n-2)初始值:f(1)=2,f(2)=3。

则f(9)=89。因此最大也才是9*89*89*81≈6000000。是可以承受的。

压缩行,有king是1,没有是0.
判断可行,就是将上一行与这一行按位与,接着左移,右移。
剩下的就是简单的dp了。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=;
int n,k,a[],b[],tp;
long long f[N][N*N][<<N],ans;
//第i行,一共摆放了j个king,第i行的摆放情况是g
void dfs(int num,int lst,int at,int bt)
{
if(num==n)
{
++tp;
a[tp]=at;
b[tp]=bt;
return ;
}
dfs(num+,lst,at,bt);
if(num-lst>=)
{
at|=(<<num);
bt++;
dfs(num+,num,at,bt);
}
}
int main()
{
scanf("%d%d",&n,&k);
dfs(,-,,);
f[][][]=;
int end=(<<n)-;
for(int i=;i<=n;i++)
for(int j=;j<=k;j++)
for(int g=;g<=end;g++)
if(f[i-][j][g]>)
for(int h=;h<=tp;h++)
if((a[h]&g)==&&(a[h]&(g<<))==&&(a[h]&(g>>))==&&j+b[h]<=k)
f[i][j+b[h]][a[h]]+=f[i-][j][g];
for(int i=;i<=end;i++)
ans+=f[n][k][i];
printf("%lld\n",ans);
return ;
}

SGU 223 little kings BSOJ2772 状压DP的更多相关文章

  1. SGU 223 Little Kings(状压DP)

    Description 用字符矩阵来表示一个8x8的棋盘,'.'表示是空格,'P'表示人质,'K'表示骑士.每一步,骑士可以移动到他周围的8个方格中的任意一格.如果你移动到的格子中有人质(即'P'), ...

  2. Kings(状压DP)

    Description 用字符矩阵来表示一个8x8的棋盘,'.'表示是空格,'P'表示人质,'K'表示骑士.每一步,骑士可以移动到他周围的8个方格中的任意一格.如果你移动到的格子中有人质(即'P'), ...

  3. SGU 132. Another Chocolate Maniac 状压dp 难度:1

    132. Another Chocolate Maniac time limit per test: 0.25 sec. memory limit per test: 4096 KB Bob real ...

  4. [SGU223]Little Kings(状压DP)

    随便DP一下 Code #include <cstdio> int sta[150],cnt[150],tp,n,k; long long dp[12][144][150],Ans; in ...

  5. 状压DP SGU 223 Little Kings

    题目传送门 /* 题意:n*n的矩阵,放置k个king,要求king互相不能攻击,即一个king的8个方向都没有另外的king,求方案个数 状态压缩DP:dp[i][num[j]][s] 代表在第i行 ...

  6. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  7. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  8. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  9. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

随机推荐

  1. SceneKit下关于修改SCNNode 的Shader展示自定义图形

    由于某些需求,需要在苹果OS x系统下展示一组点云,准备使用苹果官方的三维显示控件来完成这一功能.场景点云作为离散的点, 如果每个点以SCNnode的形式加入场景中,则回造成过大的内存消耗,笔者电脑下 ...

  2. Scala-列表操作

    package com.bigdata object ListO { def main(args: Array[String]): Unit = { println() } val list = Li ...

  3. 20145226 2016-2017-2 夏艺华 《Java程序设计》 课程总结

    20145226夏艺华 <Java程序设计>课程总结 每周读书笔记链接汇总 第一周读书笔记 了解Java编程风格,认识Java的类型与变量,掌握Java流程控制的方法(分支.循环). ht ...

  4. WebX框架的页面授权

    WebX框架的页面授权 什么是页面授权,简单来说就是对于一个Web应用程序里,哪些页面可以被哪些人在什么情况下访问进行限制.举个简单的例子,有些页面只有用户登录以后才能访问,而另外一些页面无论是否用户 ...

  5. QTableWidget具体解释(样式、右键菜单、表头塌陷、多选等) (非代理)

    在公司公示Qt开发一段时间,表格用到不少,所以,今天在这做个总结,防止以后忘记. 下面为个人模拟Windows资源管理器的一个表单.(写的比較粗糙,谅解一下) 一.设置表单样式 table_widge ...

  6. 20-[JavaScript]-BOM

    1.jsBom简介 jsBom = javascript browser object modelBOM指的是浏览器对象模型 Browser Object Model,它的核心就是浏览器. 2.Bom ...

  7. sqlmap简单中文说明

    首先下载需要的文件,如果是windows环境直接到http://sqlmap.org/下载安装所需要的文件即可. 更新 svn checkout https://svn.sqlmap.org/sqlm ...

  8. 通过ftp同步服务器文件:遍历文件夹所有文件(含子文件夹、进度条);简单http同步服务器文件实例

    该代码主要实现,指定ftp服务地址,遍历下载该地址下所有文件(含子文件夹下文件),并提供进度条显示:另外附带有通过http地址方式获取服务器文件的简单实例 废话不多说,直接上代码: 1.FTPHelp ...

  9. 模拟websocket推送消息服务mock工具二

    模拟websocket推送消息服务mock工具二 在上一篇博文中有提到<使用electron开发一个h5的客户端应用创建http服务模拟后端接口mock>使用electron创建一个模拟后 ...

  10. Java子类初始化调用父类无参构造

    实在是服了自己,子类初始化调用父类无参构造这种初学者都应该知道的事,我给忘了. 记得当初看书的时候各种概念抄在笔记本上,再上机实践,以为一辈子都不会忘,还是给忘了. 这件事说明了两个问题: 1.我没有 ...