AOJ-AHU-OJ-453 棋盘问题(位压缩)
来源:互联网 发布:数据分析师主要做什么 编辑:程序博客网 时间:2024/05/18 02:38
上次我们DFS解决了棋盘问题。但是一跑……140+ms QAQ 看到别人20+ms AC了,深感愧疚。
这次我们对棋盘问题的解决方式做空间和时间上的优化。让它优美地AC
1.考虑空间问题。我们把棋盘作为地图保存了下来。有的地方是0可以放置棋子,有的地方是-1不能放置棋子。而且还做了每列的标记,放了棋子则该标记为1。我们发现,0/1 这个计算机唯一认识的两个符号是解决该问题的关键。“位运算”。——在二进制下,一个数字只能表示为10010010或01101101这样的形式。反过来想一下,这样的形式不只可以表示其他进制的数字,还可以表示地图!
这就牵扯到位压缩的问题。棋盘上每一行的状况(反正是最大8×8棋盘),我们用一个int数表示。比如00000010(B)表示倒数第2列有一个棋子,枚举的时候,& 一下,就可以判断该列能不能放。
2.考虑时间问题。想一想,假如我已经放置了一些棋子,手里还剩下5个棋子需要放置,棋盘下面只剩下4行没有枚举。我还继续枚举一遍?浪费时间!
代码如下:
#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>int ans;int n, k;char str[10][10];int line;void dfs(int cur, int r){if(k - cur > n - r) return;//一旦剩下的棋子大于剩下的行,回城if(cur == k){ans++;return;}for(int i = 0; i < n; i++){ //↓此处是‘#’可以放置 //↓该列没有放置棋子if(str[r][i] == '#' && !(line & (1<<i))){line |= 1 << i;//在本层递归中,第 r 行 i 列被置为1,放置该棋子dfs(cur+1, r+1);//递归下一个棋子,访问下一行//完成本层递归,在此之前,进入下面的dfs,即假设没有放下棋子line ^= 1 << i;//清除此处已经放置棋子的标记}}dfs(cur, r+1);//递归没有放置该棋子的情况}int main(){//freopen("input.txt","r",stdin);while(scanf("%d%d", &n, &k) != EOF && (n != -1||k != -1)){ans = line = 0;for(int i = 0; i < n; i++)scanf("%s", str[i]);dfs(0, 0);printf("%d\n", ans);}return 0;}
0 0
- AOJ-AHU-OJ-453 棋盘问题(位压缩)
- AOJ-AHU-OJ-453 棋盘问题
- AOJ-AHU-OJ-517 序列(贪心)
- AOJ-AHU-OJ-145 流水线作业调度问题
- AOJ-AHU-OJ-2 Homework
- AOJ-AHU-OJ-9 University
- AOJ-AHU-OJ-11 Rails
- AOJ-AHU-OJ-542 Window
- AOJ-AHU-OJ-489 夺宝奇兵
- AOJ-AHU-OJ-676 投票
- AOJ-AHU-OJ-531 IPv4
- AOJ-AHU-OJ-61 Lake Counting(递归)
- AOJ-AHU-OJ-61 Lake Counting(栈)
- AOJ-AHU-OJ-460 Prime Ring Problem(栈)
- AOJ-AHU-OJ-460 Prime Ring Problem(递归)
- AOJ-AHU-OJ-460 Prime Ring Problem(巩固)
- AOJ-AHU-OJ-189 最长递增子序列(DFS)
- AOJ-AHU-OJ-595 撒哈拉大冒险(栈)
- 迭代器product
- sort命令
- Linux重定向介绍
- stringstream用法
- 连网
- AOJ-AHU-OJ-453 棋盘问题(位压缩)
- 【主席树】2012集训队互测 Middle
- Android - 使用资源(resource)
- JavaSE 反射Reflection初学
- 颜色渐变的弧度条
- 易飞小数点后位数
- 源代码Bwriter.java,从键盘输入一系列字符串,写入到磁盘(修改版)
- Algorithm学习笔记 --- 最大乘积简单枚举
- GLSL varying variable