题目:放棋子
今有6×6的棋盘,其中某些格子已预放了棋子。现在要再放上去一些,使得每行每列都正好有3颗棋子。我们希望推算出所有可能的放法,下面的代码就实现了这个功能。初始数组中,“1”表示放有棋子,“0”表示空白。请推测划线处的代码。
int N=0;
bool CheckStoneNum(int x[][6])
{ for(int k=0;k<6;k++)
{ int NumRow=0,NumCol=0;
for(int i=0;i<6;i++)
{ if(x[k][i]) NumRow++;
if(x[i][k]) NumCol++;
}
if(_____________________) return false; //填空
}
return true;
}
int GetRowStoneNum(int x[][6],int r)
{ int sum=0;
for(int i=0;i<6;i++) if(x[r][i]) sum++;
return sum;
}
int GetColStoneNum(int x[][6],int c)
{ int sum=0;
for(int i=0;i<6;i++) if(x[i][c]) sum++;
return sum;
}
void show(int x[][6])
{ for(int i=0;i<6;i++)
{ for(int j=0;j<6;j++) printf("%2d",x[i][j]);
printf("\n");
}
printf("\n");
}
void f(int x[][6],int r,int c);
void GoNext(int x[][6],int r,int c)
{ if(c<6) _________________; //填空
else f(x,r+1,0);
}
void f(int x[][6],int r,int c)
{ if(r==6)
{ if(CheckStoneNum(x)) { N++; show(x); }
return;
}
if(______________) //填空,已经放有了棋子
{ GoNext(x,r,c); return; }
int rr=GetRowStoneNum(x,r);
int cc=GetColStoneNum(x,c);
if(cc>=3) //本列已满
GoNext(x,r,c);
else if(rr>=3) //本行已满
f(x,r+1,0);
else
{ x[r][c]=1; GoNext(x,r,c); x[r][c]=0;
if(!(3-rr>=6-c||3-cc>=6-r)) //本行或本列严重缺子,则本格不能空着!
GoNext(x,r,c);
}
}
int main(int argc,char *argv[])
{ int x[6][6]={{1,0,0,0,0,0},{0,0,1,0,1,0},{0,0,1,1,0,1},{0,1,0,0,1,0},{0,0,0,1,0,0},{1,0,1,0,0,1}};
f(x,0,0);
printf("%d\n",N);
return 0;
}
解题思路:
CheckStoneNum(int x[][6])函数为检查棋盘的满行每列是否都只有三个棋子
GetRowStoneNum(int x[][6], int r)函数返回r行有几个棋子
GetColStoneNum(int x[][6], int c)函数返回c列有几个棋子
show(int x[][6])函数为打印棋盘情况
GoNext(int x[][6], int r, int c)函数确定下一枚棋子的位置,调用f(int x[][6], int r, int c)
易得
填空1为 if(NumRow != 3 || NumCol != 3) return false; 只要有一行或一列的棋子数不等于3个return false
填空2为 if(c<6) f(x, r, c+1); 因为c<6,所以该行还没有没有走到底,可以继续试探该行的下一列
填空3为 if(x[r][c] != 0) 注释就有提示,该位置放有棋子,故x[r][c] != 0
#include<iostream>
#include<cstdio>
int N = 0;
bool CheckStoneNum(int x[][6]){
for(int k=0; k<6; ++k){
int NumRow = 0, NumCol = 0;
for(int i=0; i<6; ++i){
if(x[k][i])NumRow++;
if(x[i][k])NumCol++;
}
if(NumRow!=3 || NumCol!=3)return false;
}
return true;
}
int GetRowStoneNum(int x[][6], int r){
int sum = 0;
for(int i=0; i<6; ++i){
if(x[r][i])sum++;
}
return sum;
}
int GetColStoneNum(int x[][6], int c){
int sum = 0;
for(int i=0; i<6; ++i){
if(x[i][c])sum++;
}
return sum;
}
void show(int x[][6]){
for(int i=0; i<6; ++i){
for(int j=0; j<6; ++j){
printf("%2d", x[i][j]);
}
printf("\n");
}
printf("\n");
}
void f(int x[][6], int r, int c);
void GoNext(int x[][6], int r, int c){
if(c < 6){
f(x, r, c+1);
}else{
f(x, r+1, 0);
}
}
void f(int x[][6], int r, int c){
if(r == 6){
if(CheckStoneNum(x)){
N++;
show(x);
}
return;
}
if(x[r][c]){
GoNext(x, r, c);
return;
}
int rr = GetRowStoneNum(x, r);
int cc = GetColStoneNum(x, c);
if(cc >= 3){
GoNext(x, r, c);
}else if(rr >= 3){
f(x, r+1, 0);
}else{
x[r][c] = 1;
GoNext(x, r, c);
x[r][c] = 0;
if(!(3-rr>=6-c || 3-cc>=6-r)){
GoNext(x, r, c);
}
}
}
int main()
{
int x[6][6] = {{1, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 1, 0},
{0, 0, 1, 1, 0, 1},
{0, 1, 0, 0, 1, 0},
{0, 0, 0, 1, 0, 0},
{1, 0, 1, 0, 0, 1},};
f(x, 0, 0);
printf("%d\n", N);
return 0;
}