百练 OJ 2754 八皇后问题

来源:互联网 发布:康师傅冰糖雪梨知乎 编辑:程序博客网 时间:2024/04/30 03:42

//转载请写上本帖链接:  http://www.wutianqi.com/?p=169
//及【C++奋斗乐园/ACM乐园】

/****************************************
ID: 百练 OJ 2754 八皇后问题
题目地址: http://poj.grids.cn/problem/2754/
My Name: Tanky_Woo
My Website: C++奋斗乐园|C++学习|算法学习|ACM/ICPC学习
Website Link: http://www.cpply.com/

My BBS: C++奋斗乐园|C++论坛|算法论坛|ACM/ICPC论坛
BBS Link:http://www.cppleyuan.com/

My Blog:www.wutianqi.com
豆瓣小组:http://www.douban.com/group/cppleyuan/
QQ:17611904
QQ群:C++奋斗乐园①群:19333724(满) ②群:23840480 (满)
      ③群:17314377 ④群:23829384
*****************************************/


//方法一:
此方法不用8*8的仿真棋盘来模拟控制区域,而只用一个有8个元素的数组记录已经摆放的棋子摆在什么位置,当要放置一个新的棋子时,只需要判断它与已经放置的棋子之间是否冲突就可以了。
//内存: 1848kb  时间: 0ms

#include <iostream>
using namespace std;
int ans[92][8], hang[8], num = 0;


int queen(int i)
{
 int j, k;
 if(i == 8)   //一组新的解产生
 {
  for(j = 0; j < 8; j++)
   ans[num][j] = hang[j] + 1;
  num++;
  //memset(hang, 0, sizeof(hang));  这个地方还不能置0
 }
 if(num == 93)
  return 0;
 for(j = 0; j < 8; j++)   //将当前皇后i逐一尝试放在不同的列
 {
  for(k = 0; k < i; k++)  //逐一判定i与前面的皇后是否冲突
   if(hang[k] == j || (k-i) == (hang[k]-j) || (i-k)==(hang[k]-j))
    break;
  if(k == i)
  {
   hang[i] = j;
   queen(i+1);
   hang[i] = 0;  //加了这步后由16ms变成0ms
  }
 }
}

int main()
{
 num = 0;
 queen(0);
 int n;
 scanf("%d", &n);
 for(int i = 0; i < n; i++)
 {
  int b;
  scanf("%d", &b);
  for(int j = 0; j < 8; j++)
   printf("%d", ans[b-1][j]);
  printf("/n");
 }
 return 0;
}

方法二:
用三个一维数组来分别记录每一列,每个45度的斜线,每个135度的斜线上是否已经被放置的棋子控制。
#include <iostream>
using namespace std;

int record[92][9], mark[9], count = 0;
bool range[9], line1[17], line2[17];

void tryToPut(int n);
int main()
{
 int i, nCases, num;
 scanf("%d", &nCases);

 for(i = 0; i <= 8; i++)
  range[i] = true;
 for(i = 0; i < 17; i++)
  line1[i] = line2[i] = true;

 tryToPut(1);

 while(nCases--)
 {
  scanf("%d", &num);
  for(i = 1;i <= 8; i++)
   printf("%d", record[num-1][i]);
  printf("/n");
 }
 return 0;
}

void tryToPut(int i)
{
 if(i > 8)
 {
  for(int k = 1; k < 9; k++)
   record[count][k] = mark[k];
  count++;
 }
 for(int j = 1; j <= 8; j++)
 {
  if(range[j] && line1[i+j] && line2[i-j+9])
  {
   mark[i] = j;
   range[j] = line1[i+j] = line2[i-j+9] = false;
   tryToPut(i+1);
   range[j] = line1[i+j] = line2[i-j+9] = true;
  }
 }
}


这个方法是网上的输出每种解的例子:(C++)
//八皇后问题的实现
#include <iostream>
#include <string>
using namespace std;
//QueenChess类声明
class QueenChess
{
      public:
             QueenChess();         //构造函数
             void Solve();         //求解八皇后问题,并给出放置成功的棋盘总个数
      private:
              string chessState[8];         //用于存放棋盘状态
              int solves;                   //八个皇后放置成功的棋盘解的总个数
              bool SafeJudge(int row,int col) const;    //判断位置(row,col)是否安全
              void PlaceQueen(int row);                 //在第row行放置一个皇后
              void DrawChess() const;                   //打印八个皇后放置成功的棋盘
};

//构造函数,将棋盘初始化
QueenChess::QueenChess()
{
      solves=0;
      int i=0,j=0;
      for(;i<8;++i)
      chessState[i]="--------";
}

//求解八皇后问题,并给出放置成功的棋盘总个数
void QueenChess::Solve()
{
     //从第0行开始放置皇后
     PlaceQueen(0);
     cout<<"/n八皇后问题总共的解的个数是:"<<solves<<endl;
}

//在第row行的各列放置皇后
void QueenChess::PlaceQueen(int row)
{
     //穷尽第row行的所有列
     for(int col=0;col<8;col++)
     {
             if(SafeJudge(row,col))
             {
                     //位置(row,col)安全,则放一皇后
                     chessState[row][col]='Q';
                     //若还没有放到第八行,则尝试下一行
                     if(row<7)
                        PlaceQueen(row+1);
                     //已经放置了八个皇后,打印出成功的棋盘,并将解数加1
                     else
                     {
                         solves++;
                         DrawChess();
                     }
             }//end if
             //不安全,将该处的皇后拿走,尝试下一列位置
             chessState[row]="--------";
     }
}

//判断是否(row,col)是安全位置
bool QueenChess::SafeJudge(int row,int col) const
{
     int qRow,qCol;
     //检查前面各行,看与前面的皇后是否发生攻击
     for(qRow=0;qRow<row;qRow++)
     {
           string rowState=chessState[qRow];
           //寻找第qRow行放置皇后的列数
           qCol=rowState.find("Q");
           //如果两个皇后在同一行、同一列或两条对角线上,则说明该位置不安全
           if(qRow==row||qCol==col||(qCol-qRow)==(col-row)||(qCol+qRow)==(col+row))   
              return false;
     } //end if
     return true;
}

//打印成功的棋盘
void QueenChess::DrawChess() const
{
     int i,j;
     cout<<"/n八皇后问题的第"<<solves<<" 个解为:"<<endl;
     cout<<"  0 1 2 3 4 5 6 7"<<endl;
     for(i=0;i<8;++i)
     {
           cout<<i<<" ";
           for(j=0;j<8;++j)
              cout<<chessState[i][j]<<" ";
           cout<<endl;
     } //end for
     //每打印一个成功的八皇后棋盘,暂停一下
     //system("pause");
}

//main函数进行测试
int main()
{
   QueenChess  chess;
   chess.Solve();
   system("pause");
   return 0; 
  
}

 

原创粉丝点击