• 八皇后问题


    检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

    上面的布局可以用序列2 4 6 1 3 5来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:

    行号 1 2 3 4 5 6

    列号 2 4 6 1 3 5

    这只是跳棋放置的一个解。请编一个程序找出所有跳棋放置的解。并把它们以上面的序列方法输出。解按字典顺序排列。请输出前3个解。最后一行是解的总个数。

    //以下的话来自usaco官方,不代表洛谷观点

    特别注意: 对于更大的N(棋盘大小N x N)你的程序应当改进得更有效。不要事先计算出所有解然后只输出(或是找到一个关于它的公式),这是作弊。如果你坚持作弊,那么你登陆USACO Training的帐号删除并且不能参加USACO的任何竞赛。我警告过你了!

    如果这样,会超时

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int maxn=23;
     5 int n,map[maxn][maxn],ans[maxn][maxn],cnt;
     6 bool check(int x){
     7   int j=x/n;
     8   for(int i=0;i<n;i++){
     9     if(map[j][i]==1) return false;
    10   } 
    11   j=x%n;
    12   for(int i=0;i<n;i++){
    13     if(map[i][j]==1) return false;
    14   }
    15   int xx=x/n;int yy=x%n;
    16   for(int i=1;i<n;i++){
    17     if(
    18   } 
    19 }
    20 void dfs(int x){
    21   if(x>=n*n-1){
    22     cnt++;
    23     if(cnt<=3){
    24       for(int i=0;i<9;i++)
    25         for(int j=0;j<9;j++){
    26           if(map[i][j]==1){ans[cnt][i]=j;continue;}
    27         }
    28     }
    29     return;
    30   }
    31   dfs(x+1);
    32   if(check(x)){map[x/n][x%n]=1;dfs(x+1);map[x/n][x%n]=0;}
    33 }
    34 int main(){
    35   cin>>n;
    36   dfs(0);
    37   for(int i=1;i<=3;i++){
    38     for(int j=0;j<n;j++) cout<<ans[j]<<" ";
    39     cout<<endl;
    40   }
    41   cout<<cnt<<endl;
    42   return 0;
    43 } 

    最好打标记,注意对角线的性质

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 using namespace std;
     6 const int maxn=207;
     7 int n,ans_top,pos[maxn];
     8 bool h[maxn],l[maxn],r[maxn];
     9 bool check(int x){
    10   int i=pos[x];
    11   if(h[i]==true||r[x+i]==true||l[x-i+37]==true) return false;
    12   return true;
    13 } 
    14 void dfs(int x){
    15     if(x==n){
    16       ans_top++;
    17       if(ans_top<=3){
    18         for(int i=0;i<n;i++){
    19           cout<<pos[i]+1<<" ";
    20         }cout<<endl; 
    21       }
    22     } 
    23   for(int i=0;i<n;i++){
    24     pos[x]=i;
    25     if(check(x)){
    26       pos[x]=i;h[i]=true;r[x+i]=true;l[x-i+37]=true;
    27       dfs(x+1);
    28       h[i]=false;r[x+i]=false;l[x-i+37]=false;
    29     }
    30   }
    31 }
    32 int main(){
    33   memset(pos,-1,sizeof(pos));
    34   cin>>n;
    35   dfs(0);
    36   cout<<ans_top<<endl;
    37   return 0;
    38 }
  • 相关阅读:
    weekly review 200836: the MidAutumn Festival
    weekly review 200841: Good Weekend
    解决ListView的onitemclick事件无法响应
    Android退出程序时的"再按一次退出"实现
    Android开发之文件下载
    android ExpandableListView详解
    Android ListView及其属性
    android 图片放大的处理
    android ExpandableListView
    Toast.makeText用法
  • 原文地址:https://www.cnblogs.com/lcan/p/9649144.html
Copyright © 2020-2023  润新知