回溯水题——置棋问题
2016-04-13 20:56
459 查看
题目描述
在m×n的主格中任意指定x个格子构成一个棋盘,在任一个构成的棋盘上放置k个棋子,要求任意两个棋子不得位于同一行或同一列上,要求输出满足条件的所有方案。(注意棋盘是稀疏的,即x < m*n/2。1 < m,n<10).编程要求:
1、对给定的一个棋盘,求出该棋盘可放置的最多的棋子数p.
2、记di为该棋盘上放置i个棋子时的方案总数(1<=i<=p),其中经旋转和镜面反射而得的方案记为不同的方案,对每一个i,求出相应的di。
输入
第一行是两个数字,代表棋盘的m和n,以下为一个仅由0、1组成的m×n,矩阵,某一个位置值为1表示相应的格子在这个棋盘上,为0表示相应的格子不在棋盘上。(注意m是列数,n是行数)输出
第一行是棋盘可放置的最多的棋子数p后面各行分别列出从放1个棋子到放p个棋子的方案总数。(如1:10表示放置1个棋子有10种方案,方案数不超过长整形型)
样例输入
5 5 0 1 1 1 0 0 1 0 0 0 1 1 1 0 0 0 0 1 0 0 0 0 1 1 0
样例输出
4 1:10 2:28 3:24 4:5
在这题中我们学到了以列储存和搜索的方式。
#include<cmath> #include<vector> #include<cstdio> #include<string> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 100 #define INF 2147483647 using namespace std; int m,n,g[MAXN+10][MAXN+10],plan[MAXN+10],p = 0,vis[MAXN]; void dfs(int col,int node){ //col是当前处理的列,node是已找到的节点数 if (col > m) { plan[node]++; p = max(p,node); } else for (int i=0;i<=n;i++)//0的存在是因为可以不放棋子 if (!i || g[i][col]) { bool flag = true; if (i) for (int j=1;j<col;j++) if (vis[j] == i) flag = false; if (flag) { vis[col] = i; if (!i) dfs(col+1,node); else dfs(col+1,node+1); } } } int main(){ cin >> m >> n; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&g[i][j]); memset(plan,0,sizeof plan); dfs(1,0); cout << p <<endl; for (int i=1;i<=p;i++) printf("%d:%d\n",i,plan[i]); return 0; }
相关文章推荐
- 【SDOI2014】数数
- poj 3259 Wormholes 最短路(Bellman_Ford)
- C#中的代码书写规范以及命名规范
- http协议详解之url篇
- ANR Warning,RemoteViews can only be used once ,if not 问题
- 几个性能测试工具
- c++学习之同名隐藏
- 大牛们的博客
- Bellman-Ford算法模板
- shell脚本学习笔记 (流编辑器sed)
- 素数环
- 南阳题目364-田忌赛马
- 几个性能测试工具
- C#读取Excel数据到数组
- c++中的日期和时间
- 匈牙利命名法
- POJ 2688 Cleaning Robot(状压dp+bfs)
- 基于 SoapUI 工具测试 Rest 服务
- 【ANDROID游戏开发二十四】360°平滑游戏摇杆(触屏方向导航)
- poj1061 poj2115 扩展欧几里德算法