您的位置:首页 > 其它

回溯水题——置棋问题

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: