状压入门--bzoj1087: [SCOI2005]互不侵犯King【状压dp】
Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
Sample Output
- void getnowk(int x)
- {
- int tmp=;
- while(x) tmp+=(x&),x>>=;
- nowk[cnt]=tmp;
- }
- void pre()
- {
- FAKE=(<<n)-;//可能的状态总数(最大值)
- for(int i=;i<FAKE;i++)
- if(!(i&(i>>))) bin[++cnt]=i,getnowk(i);
- }
预处理状态部分
现在我们来说状态!这种棋盘型的状压dp,我们一般把“行”作为状态。
设f[i][j][k]为在前i行,状态序号为j,目前已经放了k个国王的方案。
转移:f[i[[j][k]=sigma( f[i-1][x][k-nowk[j] ) 其中x枚举的是上一行的状态,nowk记录着此状态中放了多少国王,这里减的是当前行状态的国王数。
另外,除了同行互不侵犯,邻行是否互不侵犯我们如何处理?
无敌位运算!
- if(bin[j]&bin[k]) continue; //上下可侵犯
- if((bin[j]<<)&bin[k]) continue; // 左上右下侵犯
- if(bin[j]&(bin[k]<<)) continue; // 右上坐下侵犯
于是,这就是状压dp。它把复杂的状态转化为一个数,用位运算处理状态!
code
- #include<cstdio>
- #include<algorithm>
- //写题解的时候可以输出一下中间结果!
- using namespace std;
- typedef long long ll;
- int n,suming,cnt,FAKE;
- int bin[],nowk[];//bin[]: 01串表示的十进制
- //nowk[]: 此时放的国王数量 即01串里有多少个1
- ll f[][][];
- ll ans;
- void getnowk(int x)
- {
- int tmp=;
- while(x) tmp+=(x&),x>>=;
- nowk[cnt]=tmp;
- }
- void pre()
- {
- FAKE=(<<n)-;//可能的状态总数(最大值)
- for(int i=;i<FAKE;i++)
- if(!(i&(i>>))) bin[++cnt]=i,getnowk(i);
- }
- int main()
- {
- scanf("%d%d",&n,&suming);
- pre();//预处理出的状态 cnt是状态总数
- //所有的状态:相邻无1的01串
- for(int i=;i<=cnt;i++) f[][i][nowk[i]]=;
- //赋初值,第1行第i个状态一定只有1种方案。
- /* for(int i=1;i<=cnt;i++) printf("%d ",bin[i]);
- printf("\n");
- for(int i=1;i<=cnt;i++) printf("%d ",nowk[i]);*/
- for(int i=;i<=n;i++) //第1行已处理出,从第2行开始
- for(int j=;j<=cnt;j++)//枚举当前行(第i行)的状态
- for(int k=;k<=cnt;k++)//枚举上一行(第k行)的状态
- {
- if(bin[j]&bin[k]) continue;
- if((bin[j]<<)&bin[k]) continue;
- if(bin[j]&(bin[k]<<)) continue;
- for(int s=suming;s>=nowk[j];s--) f[i][j][s]+=f[i-][k][s-nowk[j]];
- }
- for(int i=;i<=cnt;i++) ans+=f[n][i][suming];
- printf("%lld",ans);
- return ;
- }
感谢 @KesdiaelKen @p_b_p_b 提供的思路!
*Update
用状压dp能否解决八皇后问题? 答案是否定的,在八皇后问题中要满足行、列、对角线上除了本身没有另外的皇后,因为行、列、对角线是棋盘里整条贯穿边界的线,所以用位运算压缩状态就不太行。
所以状压dp比较适合上下左右仅相邻的情况 ,这种整行的维护就比较困难。
另如https://www.luogu.org/problemnew/show/P2051 ,若把n或m中的一个范围改为10,能不能用状压dp呢?答案依然是否定的,不行的原因与八皇后问题相似。
状压入门--bzoj1087: [SCOI2005]互不侵犯King【状压dp】的更多相关文章
- [BZOJ1087] [SCOI2005] 互不侵犯King (状压dp)
Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包 ...
- BZOJ1087 SCOI2005 互不侵犯King 【状压DP】
BZOJ1087 SCOI2005 互不侵犯King Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附 ...
- BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3336 Solved: 1936[Submit][ ...
- bzoj 1087 [SCOI2005]互不侵犯King 状态压缩dp
1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MB[Submit][Status][Discuss] Descripti ...
- [bzoj1087][scoi2005]互不侵犯king
题目大意 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. 思路 首先,搜索可以放弃,因为这是一 ...
- bzoj1087: [SCOI2005]互不侵犯King (codevs2451) 状压dp
唔...今天学了状压就练练手... 点我看题 这题的话,我感觉算是入门题了QAQ... 然而我还是想了好久... 大致自己推出了方程,但是一直挂,调了很久选择了题解 坚持不懈的努力的调代码. 然后发现 ...
- [BZOJ1087][SCOI2005]互不侵犯King解题报告|状压DP
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 好像若干月前非常Naive地去写过DFS... ...
- 【BZOJ1087】 [SCOI2005]互不侵犯King 状压DP
经典状压DP. f[i][j][k]=sum(f[i-1][j-cnt[k]][k]); cnt[i]放置情况为i时的国王数量 前I行放置情况为k时国王数量为J #include <iostre ...
- BZOJ 1087 [SCOI2005]互不侵犯King ——状压DP
[题目分析] 沉迷水题,吃枣药丸. [代码] #include <cstdio> #include <cstring> #include <iostream> #i ...
随机推荐
- HDU 1244 【DP】
题意: 中文. 思路: 先初步处理,用give-take求出每个城市剩的钱. 求解问题转化成使得和不小于0的最长连续字串. 枚举起点,然后当该起点加的和为负时开始枚举下一起点.(这个状态的转移) 2W ...
- 某考试 T1 arg
题目描述 给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. 输入格式 第一行两个整数 n, m. 接下来一行 m 个整数, 表示 A. 输出格式 ...
- java学习(4)——动手动脑
根据ppt所给的例子,运行的结果如下所示: ppt中出现的第二个动手动脑如下: 代码如下: 其运行结果如下: 作出简单的分析如下:有点类似于if 和else的关系,总是对应try和catch同层中的异 ...
- http://www.ybtsoft.com/
http://www.ybtsoft.com/ 可视化作流建模 http://www.ybtsoft.com/t3/bpm/ 慧都控件网 写一本关于互联网商业变现的书
- HDU 5280 Senior's Array
Senior's Array Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) T ...
- 如何扩展ArcGIS中的元数据编辑器
http://www.esrichina-bj.cn/old../library/arcnews16/Metadata.htm http://www.esrichina-bj.cn/old../lib ...
- 相机标定(Camera calibration)
简单介绍 摄像机标定(Camera calibration)简单来说是从世界坐标系换到图像坐标系的过程.也就是求终于的投影矩阵 P 的过程,以下相关的部分主要參考UIUC的计算机视觉的课件(网址Spr ...
- Deepin-快捷方式设置
Linux无非就是命令命令命令,而不是点点点,下面介绍快捷方式 然后点击 最后找到快捷方式(鼠标滚轮下滑) 快捷方式自个看着修改
- python05-09
一.lambda表达式 def f1(): return 123 f2 = lambda : 123 def f3 = (a1,a2): return a1+a2 f4 = lambda a1,a2 ...
- vue 自定义 移动端筛选条件
1.创建组件 components/FilterBar/FilterBar.vue <template> <div class="filterbar" :styl ...