zoukankan      html  css  js  c++  java
  • 回溯经典(指定位置N皇后问题)

    N皇后问题自不必多说,这道题的先行条件是在放置的时候已经指定了一个棋子的位置。

    输入第一行为N,第二行为指定棋子的坐标(x,y);输出方案总数以及按字典序升序的各种方案。

    思路:
    首先是回溯,其次对待指定棋子有三种方法:

    1. 枚举所有情况,最后判断
    2. 在枚举到那一行的时候只让棋子下在指定的那一列
    3. 初始化vis数组时进行标记,同时跳过枚举x行和y列

    第三种我没写出来,但很明显比前两种要快得多,第二种比第一种快了100多ms

    代码如下:
    第一种,耗时327ms:

    #include<cstdio>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    int n, x, y, tot = 0;
    int vis[3][100], c[20];
    int ans[1000000][20];
    
    void search(int cur) {
        if (cur == n) {
            if (c[x] != y) return;
            memcpy(ans[tot], c,sizeof(c));
            tot++;
        }
        else for (int i = 0; i < n; i++) {
            if (!vis[0][i] && !vis[1][cur + i] && !vis[2][cur - i + n]) {
                c[cur] = i;
                vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 1;
                search(cur + 1);
                vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 0;
            }
        }
    }
    
    int main() {
        scanf("%d", &n);
        scanf("%d%d", &x, &y);
        x--; y--;
        search(0);
        printf("%d
    ", tot);
        for (int i = 0; i < tot; i++) {
            for(int j = 0; j < n; j++) {
                printf("%d ", ans[i][j] + 1);
            }
            printf("
    ");
        }
        return 0;
    }

    第二种,耗时221ms

    #include<cstdio>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    int n, x, y, tot = 0;
    int vis[3][100], c[20];
    int ans[1000000][20];
    
    void search(int cur) {
        //if (cur == x) { c[cur] = y; search(cur + 1); return; }
        if (cur == n) {
            //if (c[x] != y) return;
            memcpy(ans[tot], c, sizeof(c));
            tot++;
        }
        else for (int i = 0; i < n; i++) {
            if (cur == x&&i != y)continue;
            if (!vis[0][i] && !vis[1][cur + i] && !vis[2][cur - i + n]) {
                c[cur] = i;
                vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 1;
                search(cur + 1);
                vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = 0;
            }
        }
    }
    
    int main() {
        scanf("%d", &n);
        scanf("%d%d", &x, &y);
        x--; y--;
    
        search(0);
        printf("%d
    ", tot);
        for (int i = 0; i < tot; i++) {
            for (int j = 0; j < n; j++) {
                printf("%d ", ans[i][j] + 1);
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    界面实现的小总结
    创建线程的三种方式
    之前总结的今天给大分享一下iOS
    MVVM
    响应者链条
    layer图层常见属性
    NSRunLoop && NSTimer
    关于Angularjs做的一个购物车小例子
    css中实现元素的绝对居中
    剑指 Offer 18. 删除链表的节点 链表
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489818.html
Copyright © 2011-2022 走看看