首页新闻找找看学习计划

大家对于N皇后问题,有什么高明的解法,一起探讨一下。

0
悬赏园豆:50 [已解决问题] 解决于 2019-11-14 18:49

N皇后问题

N 皇后问题,就是在一个N * N 的棋盘中,摆放N个皇后棋子,这两N个皇后不能出现 两个在同一横线,同一竖线,同一斜线上。

请大家各抒己见,畅所欲言。

补充:

不是高明的解法,是用最短,最优雅的代码。

`

Shendu.CC的主页 Shendu.CC | 小虾三级 | 园豆:1771
提问于:2019-08-27 11:42
< >
分享
最佳答案
0
#include<bits/stdc++.h>
using namespace std;
template <typename T>
void read(T &x) {
    int f = 1;
    x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar())
        if (c == '-')
            f = -f;
    for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
    x *= f;
}
char s[100005];
struct node{
    int id,len,num;
}f[100005];
int l[100005],r[100005];
bool cmp(node x,node y){
    if(x.num*y.len!=y.num*x.len)
        return x.num*y.len>y.num*x.len;
    else
        return x.num<y.num;
}
int use[100005];
int main(){
    freopen("tiaoxingma.in","r",stdin);
    freopen("tiaoxingma.out","w",stdout);
    int T;
    read(T);
    for(;T;T--){
        memset(use,0,sizeof(use));
        int n,k;
        read(n),read(k);
        scanf("%s",s+1);
        int tot=1;
        f[tot].id=1;
        f[tot].len=1;
        f[tot].num=1;
        for(int i=2;i<=n;i++){
            if(s[i]!=s[i-1]){
                f[++tot].id=i;
                f[tot].len=1;
                f[tot].num=2;
            } else {
                f[tot].len++;
            }
        }
        f[tot].num--;
        int l_len=f[1].len;
        int r_len=f[tot].len;
        sort(f+1,f+1+tot,cmp);
        int l_id=0;
        int r_id=0;
        for(int i=1;i<=tot;i++){
            if(f[i].id==1) l_id=i;
            if(f[i].id+f[i].len-1==n) l_id=i;
        }
        int cnt=tot;
        int st=1;
//      int ans=0;
        while(cnt>k){
            if(cnt-k==1){
                bool can_l=false,can_r=false;
                if(l_len*2>f[st].len&&!use[l_id]) can_l=true;
                if(r_len*2>f[st].len&&!use[r_id]) can_r=true;
                if(can_l==true&&can_r==true){
                    if(f[l_id].len<f[r_id].len) can_r=false;
                    if(f[l_id].len>f[r_id].len) can_l=false;
                }
                if(can_l==true&&can_r==false){
                    for(int j=f[l_id].id;j<=f[l_id].id+f[l_id].len-1;j++) s[j]='0'+'1'-s[j];
                    cnt--;
                    continue;
                }
                if(can_l==false&&can_r==true){
                    for(int j=f[r_id].id;j<=f[r_id].id+f[r_id].len-1;j++) s[j]='0'+'1'-s[j];
                    cnt--;
                    continue;
                }
            }
            use[st]=true;
            cnt-=f[st].num;
            for(int j=f[st].id;j<=f[st].id+f[st].len-1;j++) s[j]='0'+'1'-s[j];
            use[st+1]=true;
            use[st-1]=true;
            for(;st<=tot;st++){
                if(use[st]==false) break;
            }
        }
        for(int i=1;i<=n;i++) printf("%c",s[i]);
        printf("\n");
    }
    return 0;
}
/*
3
9 3
000111000
10 3
0111011010
4 4
0001
*/

题目略不一样,就是改为放K个皇后。
用位运算优化

收获园豆:30
Dark_Lord | 菜鸟二级 |园豆:240 | 2019-11-14 18:25

@Shendu.CC

Dark_Lord | 园豆:240 (菜鸟二级) | 2019-11-14 18:27
其他回答(2)
0

没啥高明的解法,就百度里说的回溯法。如果用栈,可能会简单一点

收获园豆:10
会长 | 园豆:5534 (大侠五级) | 2019-08-27 11:48

好的。那么广搜呢?

支持(0) 反对(0) Shendu.CC | 园豆:1771 (小虾三级) | 2019-08-27 12:26

@Shendu.CC: 没听过呀,孤陋寡闻了。

支持(0) 反对(0) 会长 | 园豆:5534 (大侠五级) | 2019-08-27 12:39

@会长: 为什么用栈会简单呢?用栈模拟递归吗?

支持(0) 反对(0) Shendu.CC | 园豆:1771 (小虾三级) | 2019-08-27 13:18

@Shendu.CC: n个位置都不满足条件就可以把上一个皇后出栈重新安排位置,感觉容易点

支持(0) 反对(0) 会长 | 园豆:5534 (大侠五级) | 2019-08-27 13:22

@Shendu.CC:

class Queen(object):
    def __init__(self, row, column):
        self.__row = row
        self.__column = column
    
    @property
    def row(self):
        return self.__row

    @row.setter
    def row(self, value):
        self.__row = value

    @property
    def column(self):
        return self.__column

    @column.setter
    def column(self, value):
        self.__column = value

def valid(row, column, stack):
    for item in stack:
        if item.row == row:
            return False
        if item.column == column:
            return False
        if abs(item.row - row) == abs(item.column - column):
            return False
    return True

def fuckQueen(n):
    row = 0
    column = 0  
    stack = []

    while row < n:
        done = False
        for column_index in range(column, n):
            if valid(row, column_index, stack):
                stack.append(Queen(row, column_index))
                done = True
                row += 1
                column = 0
                break
        if done == False:
            queen = stack.pop()
            row -= 1
            column = queen.column + 1

    return stack

if __name__ == "__main__":
    
    stack = fuckQueen(4)
    for item in stack:
        print(item.row, ' ', item.column)

我只给出一个解,没有遍历所有解,不管怎么说,用了栈,你不用栈试试会不会比这个复杂

支持(0) 反对(0) 会长 | 园豆:5534 (大侠五级) | 2019-08-27 14:03

@会长: 稍等哦。

支持(0) 反对(0) Shendu.CC | 园豆:1771 (小虾三级) | 2019-08-27 14:16

@Shendu.CC: 刚才有个地方写错了,我改了下,应该是break,不是continue

支持(0) 反对(0) 会长 | 园豆:5534 (大侠五级) | 2019-08-27 14:18

@会长:

c++ 递归

class Solution {
public:
    vector<vector<string>> ans;
    int a[100][100];
    int m;
    vector<vector<string>> solveNQueens(int n) {
        
        m=n;
        memset(a,0,sizeof(a));
        fun(0);
        
        return ans;
    }
      
    
    void fun(int pos)
    {
        if(pos==m)
        {
            ans.push_back(getString());
            return;
        }
        for(int i=0;i<m;i++)
        {
            if(a[pos][i]==0)
            {
                a[pos][i]=1;
                setLock(pos,i,2);
                fun(pos+1);
                setLock(pos,i,-2);
                a[pos][i]=0;
            }
        }
    }
    void setLock(int x,int y,int num)
    {
        for(int i=x+1;i<m;i++)
        {
            a[i][y]+=num;
        }
        int tag=1;
        for(int i=x+1;i<m;i++)
        {
            if(y+tag<m)
                a[i][y+tag]+=num;
            if(y-tag>=0)
                a[i][y-tag]+=num;
            
            tag++;
        }
    }
    
    vector<string> getString()
    {
        vector<string> res;
       
        for(int i=0;i<m;i++)
        {
            string s="";
            for(int j=0;j<m;j++)
            {
                if(a[i][j]==1)
                {
                    s+='Q';
                }
                else
                    s+='.';
            }
            res.push_back(s);
        }
        return res;
    }
    
};
支持(0) 反对(0) Shendu.CC | 园豆:1771 (小虾三级) | 2019-08-27 15:09

@会长: https://leetcode.com/problems/n-queens/

你可以用python把这道题目过一下,我不会python 不好改你的代码。

支持(0) 反对(0) Shendu.CC | 园豆:1771 (小虾三级) | 2019-08-27 15:12

@Shendu.CC: 我没看懂,啊哈哈。我小时候上学老师出过这个题目,记得当时不会写,从网上找的代码,不过没有用到栈,也是回溯法。感觉用栈方便一些。

关键代码的行数,我看你的c++代码比我的python代码还多一点。虽然看不懂,但是我觉得用栈代码会少一点,你用栈试试

支持(0) 反对(0) 会长 | 园豆:5534 (大侠五级) | 2019-08-27 15:48

@会长: @会长: 我用了 栈的
https://leetcode.com/problems/n-queens-ii/

过了这一题。

class Solution {
public:
    int ans=0;
    int a[100][100];
    int m;
    int x[100005];
    int y[100005];
    int s[100005];
    int p[100005];
    int totalNQueens(int n) {

        m=n;
        memset(a,0,sizeof(a));
        int pos=0;
        s[pos]=0;
        x[pos]=-1;
        y[pos]=-1;
        p[pos]=-1;
        pos++;
        while(pos!=0)
        {
            int i=s[pos-1];
            
            if(i==n)
            {  
                ans++; 
            }

            if(p[pos-1]<=n-1&&i!=n)
            {
                p[pos-1]++;
                while(a[i][p[pos-1]]!=0)
                {
                    p[pos-1]++;
                }
                if(p[pos-1]!=n){
                    
                
                a[i][p[pos-1]]=1;
                setLock(i,p[pos-1],2);
                s[pos]=i+1;
                x[pos]=i;
                y[pos]=p[pos-1];
                p[pos]=-1;
                pos++;
                
                continue;
                }
            }
           
            if(pos==1)
                break;
            
            a[x[pos-1]][y[pos-1]]=0;
            setLock(x[pos-1],y[pos-1],-2);
            pos--;
        }
        
        return ans;
        
    }
    
    void setLock(int x,int y,int num)
    {
        for(int i=x+1;i<m;i++)
        {
            a[i][y]+=num;
        }
        int tag=1;
        for(int i=x+1;i<m;i++)
        {
            if(y+tag<m)
                a[i][y+tag]+=num;
            if(y-tag>=0)
                a[i][y-tag]+=num;
             
            tag++;
        }
    }
     
  
};
支持(0) 反对(0) Shendu.CC | 园豆:1771 (小虾三级) | 2019-08-27 19:50

@Shendu.CC: 赞

支持(0) 反对(0) 会长 | 园豆:5534 (大侠五级) | 2019-08-28 08:23
0

可以用位运算优化

收获园豆:10
End_donkey | 园豆:212 (菜鸟二级) | 2019-08-27 17:20
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册