洛谷 P1896 [SCOI2005]互不侵犯

洛谷传送门

题目描述

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

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

输入格式

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

输出格式

所得的方案数

输入输出样例

输入 #1复制

输出 #1复制

题解:

原谅我一开始看到题还以为是爆搜。。。

其实是一道状态压缩的题目。

蒟蒻自己一个比较大的进步就是把自己状态设置对了...

设置:\(dp[i][j][k]\)为第\(i\)行状态为\(j\)、已经用了\(k\)个国王时的方案数。

状态压缩大体有这么几步:设置状态\(\rightarrow\)考虑转移方式\(\rightarrow\)按转移方式考虑预处理和判断转移条件\(\rightarrow\)开始转移\(\rightarrow\)统计答案。

那么我们设置好状态,开始考虑转移方式:我们发现,若是想从第\(i-1\)行开始转移,转移的条件一是当前和上一次的状态,但是,这些状态的改变必然还会改变国王的个数。也就是说,这数组的两维是有联系的,是自变量和因变量的关系。所以我们因此想到,既然是自变量和因变量的关系,我们莫不如由此构建一个映射,存下来每个状态和每个状态需要的国王人数。这样我们转移的时候就没啥问题了。

如何预处理呢?我们想到,我们需要按行处理状态,每个状态有放国王和不放国王两种选择。因为是预处理,我们是肯定不能用递推和\(DP\)的(你想干啥)

所以我们考虑搜索。

一次搜索可以处理出所有合法的行的方式。

这里插一嘴,因为我们已经把所有合法的行的方式都求出来了,所以我们没必要再把\(dp\)数组的第二维开那么大,构建好映射关系之后,直接用\(cnt\)代替这个二进制状态即可。(因为\(1-cnt\)的每个数都对应着一个数组\(s[i]\)作为状态。)

然后再转移的时候进行判断是否合法就可以。

转移方程:

\[dp[i][j][l]+=dp[i-1][k][l-num[j]]
\]

这里的\(k,j\)分别表示一种状态。

代码:

#include<cstdio>
#define int long long
using namespace std;
int n,K,cnt,ans;
int s[100],num[100];
int dp[10][100][110];
//dp[i][j][k]表示前i-1行放完,第i行状态为j、有k个国王时的方案数
//状态0/1:0:国王攻击不到;1:被国王占领
void dfs(int pos,int st,int tot)
{
if(pos>=n)
{
s[++cnt]=st;
num[cnt]=tot;
return;
}
dfs(pos+1,st,tot);
dfs(pos+2,st+(1<<pos),tot+1);
}
signed main()
{
scanf("%lld%lld",&n,&K);
dfs(0,0,0);
for(int i=1;i<=cnt;i++)
dp[1][i][num[i]]=1;
for(int i=2;i<=n;i++)
for(int j=1;j<=cnt;j++)
for(int k=1;k<=cnt;k++)
{
if(s[j]&s[k])
continue;
else if(s[j]&(s[k]>>1))
continue;
else if(s[j]&(s[k]<<1))
continue;
else
for(int l=num[j];l<=K;l++)
dp[i][j][l]+=dp[i-1][k][l-num[j]];
}
ans=0;
for(int i=0;i<=cnt;i++)
ans+=dp[n][i][K];
printf("%lld",ans);
return 0;
}

SCOI 2005 互不侵犯的更多相关文章

  1. C++之路进阶——codevs2451(互不侵犯)

    2451 互不侵犯 2005年省队选拔赛四川  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master       题目描述 Description 在N×N的棋盘里 ...

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

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

  3. [bzoj1087][scoi2005]互不侵犯king

    题目大意 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. 思路 首先,搜索可以放弃,因为这是一 ...

  4. 【状压DP】bzoj1087 互不侵犯king

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

  5. BZOJ-1087 互不侵犯King 状压DP+DFS预处理

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2337 Solved: 1366 [Submit][ ...

  6. SCOI2005互不侵犯King

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

  7. 洛谷1377 M国王 (SCOI2005互不侵犯King)

    洛谷1377 M国王 (SCOI2005互不侵犯King) 本题地址:http://www.luogu.org/problem/show?pid=1377 题目描述 天天都是n皇后,多么无聊啊.我们来 ...

  8. CODEVS 2451 互不侵犯

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

  9. 洛谷 P1896 互不侵犯King

    P1896 [SCOI2005]互不侵犯King 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共 ...

随机推荐

  1. 垃圾收集器GC

    (1)DefNew(串行)收集器 Serial(串行)垃圾收集器是最基本.发展历史最悠久的收集器:JDK1.3.1前是HotSpot新生代收集的唯一选择: 特点: (1) 针对新生代采用复制算法,单线 ...

  2. xampp配置二级域名通过不同端口访问不同网站

    首先需要在xampp\apache\conf\extra\httpd-vhost.conf中写入配置的二级域名 <VirtualHost *:8081> // 该网站通过监测8081端口 ...

  3. sqlite3 国产化如何添加密码

    sqlite3 国产化如何添加密码 sqlite3 国产化如何添加密码sqlite3 国产化如何添加密码

  4. C++ class内类型重载,operator Type()

    #include <iostream> // operator Type() 类型操作符重载 // operator int() // operator double() // ... / ...

  5. Java流程控制之顺序结构

    概述 在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.也就是说,程序的流程对运行结果有直接的影响.所以,我们必须清楚每条语句的执行流程.而且,很多时候我们要通过控制语句的执行顺序 ...

  6. BZOJ2591/LG3047 「USACO12FEB」Nearby Cows 换根树形DP

    问题描述 BZOJ2591 LG3047 题解 换根树形DP. 设 \(opt[i][j]\) 代表 当 \(1\) 为根时,\(i\) 为根的子树中,到 \(i\) 的距离为 \(j\) 的权值和 ...

  7. Node.js使用Nodemailer发送邮件

    除了Python,在node中收发电子邮件也非常简单,因为强大的社区有各种各样的包可以供我么直接使用.Nodemailer包就可以帮助我们快速实现发送邮件的功能. Nodemailer简介 Nodem ...

  8. 【2019.8.20 NOIP模拟赛 T3】小X的图(history)(可持久化并查集)

    可持久化并查集 显然是可持久化并查集裸题吧... 就是题面长得有点恶心,被闪指导狂喷. 对于\(K\)操作,直接\(O(1)\)赋值修改. 对于\(R\)操作,并查集上直接连边. 对于\(T\)操作, ...

  9. Python连载49-正则举例

    一.re举例 import re #查找数字 p = re.compile(r"\d+") #在字符串“ongahjeuf125”中及逆行查找,按照规则p指定的正则进行查找 m = ...

  10. HTML连载43-还原字体和字号、文字界面

    一.还原字体和字号 1.利用fireworks切片以及文本添加的功能可以用来定位我们想要的文字是什么字体,行高又是多少,但其实很low,是我们人工挑选出来的. 2.注意点:在企业开发中,如果一个盒子中 ...