checker Challenge 跳棋的挑战

题目如下:
checker Challenge 跳棋的挑战
检查一个如下的6 x 6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行,每列,每条对角线(包括两条主对角线的所有对角线)上都至多有一个棋子。

1 2 3 4 5 6

1 | | O | | | | |

2 | | | | O | | |

3 | | | | | | O |

4 | O | | | | | |

5 | | | O | | | |

6 | | | | | O | |

上面的布局可以用序列2 4 6 1 3 5 来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6
列号 2 4 6 1 3 5
这只是跳棋放置的一个解.请编写一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。
解按字典顺序排列。请输出前3个解。最后一行是解的总个数。
INPUT FORMAT
一个数字N (6 <= N <= 13) 表示棋盘是N x N 大小的。
SAMPLE INPUT(checker.in)
6
OUTPUT FORMAT
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
SAMPLE OUTPUT(checker.out)
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4
解题思路:
这一题实际上就是一个N皇后问题,用DFS就可以过,每对角线可以表示为:
b[行+列]和b1[列-行+N-1] ,列为:b2[列]
所以代码如下:

#include<cstdio>
#include<cstdlib>
int n,ans=0;
int bj1[50],b[100],a[50],bj[100];
void get(int &x) {
    char c = getchar();
    x = 0;
    while(c < '0' || c > '9') c = getchar();
    while(c <= '9' && c >= '0') x = x*10+c-48, c = getchar();
}
void put(int x) {
    int num = 0;
    char c[15];
    while(x) c[++num] = (x%10)+48, x /= 10;
    while(num) putchar(c[num--]);
    putchar('\n');
}
void dfs(int k) {
    if(k==n+1) {
        if(ans<3) {//输出前三个 
            for(register int i=1; i<k; i++)
                put(a[i]);
            printf("\n");
        }
        ans++;//总是+1 
        return ;//返回 
    }
    for(register int i=1; i<=n; i++) {
        if(bj1[i]==0&&b[i+k]==0&&bj[i-k+n-1]==0) {//保证使得每行,每列,每条对角线(包括两条主对角线的所有对角线)上都至多有一个棋子 
            bj1[i]=1;
            b[i+k]=1;
            bj[i-k+n-1]=1;
            a[k]=i;
            dfs(k+1);
            bj1[i]=0;
            b[i+k]=0;
            bj[i-k+n-1]=0;
        }
    }
}
int main() {
    freopen("checker.in","r",stdin);
    freopen("checker.out","w",stdout);
    get(n);
    dfs(1);//从第一行开始搜索 
    put(ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值