POJ 1321 棋盘问题

传送门:http://poj.org/problem?id=1321

 

分析:

    此题与8皇后问题类似,关键如下:

    第一、并不是每一个格子都可以放棋子

    第二、并不是对应n行n列的棋盘一定要放n个棋子

    第三、约束条件较八皇后问题少了必须不能再同一斜线上

    综上,此题在八皇后问题的基础上需要修改的重要点有:

    第一、在backtrace函数中,当已经放置的棋子数达到k个时,需要返回;当到最底层时,需要返回。

    第二、此时的Loca数组没有必要再去记录第i行的棋子放置位置,因为有可能这一行根本就不放棋子。

 

    在注意了上述事项后,此题的思路就很清晰了:

    从第一行第一列开始,判断此行列能否放置棋子,如果可以,我们有两种选择,放或不放,每种情况都需要对相应的sum和loca作修改,loca[i]=0表示第i列还没有放置,=1则表示已经放过棋子了,这样就可以得到剪枝函数为loca[i]=0且input[m][i]='#'。需要特别注意的是,如果不放棋子的话,backtrace函数是可以放在for循环内的每一次改变后,也可以放在for循环外,但是在前者会做很多无用功,增加了回溯的次数,造成超时,无法通过,当我把这个backtrace放在外面时,POJ就提示AC了。

   代码如下:

#include <stdio.h>
char input[10][10];
int sum  , num ;
int n , k ;
int loca[10];//loca[i]=0表示第i列没有放置棋子,=1表示放了棋子

int place(int p , int q)
//判断p行q列能否放棋子的关键
//第一是第q列是否放过棋子
//第二是第p行q列是否为#
{
    return loca[q]==0&&input[p][q]=='#';
}

void backtrace(int t)
{
    int i;
    if(num == k)
      sum++;
    else
      if(t >= n)
        return ;
      else
      {
          for(i = 0 ; i < n ; i ++)
          {
              if(place(t,i))//如果第t行第i列可以放置
              {
                  num ++ ;//放过的棋子增1
                  loca[i] = 1;//表示第i列放过棋子了
                  backtrace(t+1);//如果在这一列放棋子的话则按此纵深
                  num --;
                  loca[i] = 0;//表示在这一列不放棋子
                  //backtrace(t+1);
              }
          }
          backtrace(t+1);
      }
}

int main()
{
    int  i;
    while(scanf("%d%d",&n,&k)==2)
    {
        if(n==-1&&k==-1)
        return 0;
        for(i = 0 ; i < n ; i ++)
          scanf("%s",input[i]);
        memset(loca,0,sizeof(loca));//对loca函数置零,表示每一列都还没有放
        backtrace(0);
        printf("%d\n",sum);
        sum = 0;
        num = 0;
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值