C語言實現N皇后問題非遞迴求解

來源:互聯網
上載者:User

C語言實現N皇后問題非遞迴求解

N皇后問題是一個老掉牙的問題了,隨便翻一本演算法書籍都能看到對它的介紹,其實N皇后問題可以用非遞迴方法解決,有效避免N過大時的遞迴工作棧溢出,且佔用的儲存空間較小,運行速度也較快,達到運行速度和空間合理利用的兩全,代碼很簡單,並不複雜,有時簡單也是一種美,意味著可靠和高效。追求程式的複雜和難以理解的編程者不會認同這一點,但對用簡單的設計就可以解決的問題用複雜的資料表示加以描述是沒有必要的。

代碼如下(C語言):

#include <stdio.h>
#include <malloc.h>
#include <math.h>
int place(int i, int k, int *p);  //檢查k+1行i列能否放置皇后,能返回1,否則返回0
int find(int n, int *p, int k);  //在k+1行搜尋可以放置皇后的位置,找到位置後返回列標,否則返回0
void output(int n, int *p);  //輸出n皇后問題的一個解

void main()
{
    int k, n;
    int m;
    int *p;

    printf("you want to solve n queens problem\n");
    printf("n=");
    scanf("%d", &n);                  //輸入問題規模

    p=(int *) malloc(n*sizeof(int));  //p[k]表示k+1行皇后所在列
    for (k=0; k<n; k++)
    {
        p[k]=0;                    //初始化數組p                     
    }

    k=0;      //初始化為第一行
    m=0;      //記錄解的個數變數初始化
loop: if (k==0)  //進入或回溯至第一行
      {
          p[k]=p[k]+1;  //試探下一列

          if (p[k]>n)    //第一行所有列試探完畢,回溯結束
          {
              goto exit;
          }

          k++;    //試探下一行
          goto loop;
      }
      else
      {
          if (find(n, p, k)==0)    //k+1行沒有找到可放置皇后的位置
          {
              p[k]=0;            //必要的清理
              k--;                //回溯
              goto loop;
          }
          else
          {
              p[k]=find(n, p, k);    //在k+1行找到的位置賦予p[k]
              if (k!=(n-1))    //皇后沒有全部放置完畢
              {
                  k++;          //試探下一行
                  goto loop;
              }
              else        //皇后全部放置成功,找到解
              {
                  m++;   
                  printf("The %dnd solution\n", m);
                  output(n, p);    //輸出解

                  goto loop;  //回溯
              }
          }
      }

exit: ;
      printf ("There are %d solutions in total\n", m);  //輸出解的個數
}

int place(int i, int k, int *p)
{
    int m;

    for (m=0; m<k; m++)
    {
        if ((p[m]==i)||(abs(m-k)==abs(p[m]-i)))  //k+1行i列不是合法位置
            return (0);
    }

    return (1);  //k+1行i列是合法位置   
}

int find(int n, int *p, int k)
{
    int i;
    i=p[k];

    for (i++; i<=n; i++)
    {
        if (place(i, k, p)==1)  //在k+1行找到可放置皇后的列
            return (i);    //返回該列
    }
    return (0);  //在k+1行沒有找到可放置皇后的列
}

void output(int n, int *p)
{
    int i, j;

    for (i=0; i<n; i++)
    {
        for (j=1; j<=n; j++)
        {
            if (j==p[i])
                printf("1 ");
            else
                printf("0 ");
        }
        printf("\n");
    }
    printf("\n");
}

附n皇后問題的遞迴代碼:

該程式段為自己的創作(教科書上現成的代碼沒必要複製粘貼),意義不是很大,因為比較繁瑣,當n<=8時能輸出正確結果,n>8時直接STACKOVERFLOW,所以大家看看就好,並不實用

#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <stdlib.h>
void print(int n);
void put(int k, int n, int *q, int *p);
void output(int n, int *p);
int law(int k ,int i, int *p);

void main ()
{
    int n;
    printf ("you want to solve the problem of n queens the n=?\n");
    scanf ("%d", &n);
    print(n);
}

void print(int n)
{
    int number, i;
    int *p;
    number=0;
    p=(int *)malloc(n*sizeof(int));
    for (i=0; i<n; i++)
        *(p+i)=0;

    put(1, n, &number, p);

    printf("There are %d solutions in total\n", number);
    free(p);
}
void put(int k, int n, int *q, int *p)
{
    int i;
    if (k==1)
    {
        (*p)++;
        if ((*p)>n)
            return;
        put(k+1, n, q, p);
    }
    else
    {
        i=*(p+k-1);
        i++;
        while (i<=n)
        {
            if (law(k, i, p))
            {
                *(p+k-1)=i;
                if (k==n)
                {
                    (*q)++;
                    printf ("The %dnd solution\n", *q);
                    output(n, p);
                    put(k, n, q, p);
                }
                else
                {
                    put(k+1, n, q, p);
                }
                break;
            }
            i++;
        }
        if (i>n)
        {
            *(p+k-1)=0;
            put(k-1, n, q, p);
        }
    }
}

void output(int n, int *p)
{
    int j, c;
    for (j=1; j<=n; j++)
    {
        for (c=1; c<=n; c++)
        {
            if (c==*(p+j-1))
                printf ("%d", 1);
            else
                printf ("%d", 0);
        }
        printf ("\n");
    }
    printf ("\n");
}

int law(int k ,int i, int *p)
{
    int m;
    for (m=1; m<k; m++)
    {
        if ((*(p+m-1)==i)||(abs(m-k)==abs(*(p+m-1)-i)))
            return(0);
    }
    return(1);
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.