八皇后问题求解的C语言程序的实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了八皇后问题求解的C语言程序的实现相关的知识,希望对你有一定的参考价值。

若为n皇后问题就是在n*n的棋盘上放置n个皇后 。
〔基本要求〕八皇后问题是一个古老的搜索问题,可以用递归算法来实现,在递归过程中,一一测试每一种放法,直到得出全部正确答案为止。
〔实现提示〕定义一个8*8的二维数组(为方便处理,下标范围为1:8为好);
对数组进行初始化;(全置空)
从n行开始放置第一个皇后(满足一行只有一个皇后的要求)后
对1~8列进行测试;若满足条件则保存皇后所在位置,直到所有皇后放置好;
输出每一个皇后应放置的位置

这是个前不久,我为别人写的一个代码;
八皇后问题共有92种解;
以下代码是解决:对于固定一个皇后位置,输出所有可能情况.
如果这不适合你的答案你可以,稍微改改的哦~~

代码如下:

#include "stdio.h"
bool board[8][8]=0;
int num=0; //满足条件的个数
int inix,iniy; //输入一个皇后的初始位置
void output() //输出

int i, j;
for(i=0;i<8;i++)

for(j=0;j<8;j++)

if(!board[i][j]) printf("■ ");
else printf("◆ ");

printf("\n");

num++;
printf("\n\n");
return ;


bool check(int x,int y) //判断是否能放

int i, j ;
for(i=0; i<8 ; i++)


if(board[i][y]==1) return false;


for(i=0;i<8;i++)

if(board[x][i]==1) return false;


i=x; j=y;

while(i>0 && j>0 ) i--; j--;
for(;i<8 && j<8 ; i++,j++)
if(board[i][j]==1) return false;

i=x; j=y;
while(i>0 && j<7 ) i--;j++;
for(;i<8 && j>=0 ; i++ ,j--)
if(board[i][j]==1) return false ;
return true ;


void search(int x,int num) // 搜索函数

int i;
if(num>=8) output(); return ;
if(x==inix-1) search(inix,num+1);
else

for(i=0;i<8;i++)

if(check(x,i))

board[x][i]=1;
search(x+1,num+1);
board[x][i]=0;



return ;


int main()

scanf("%d %d",&inix,&iniy);
board[inix-1][iniy-1] = 1 ;
search(0,0);
printf("%d\n",num);
return 0;


例如:
输入 : 1 1
输出 :
◆ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ◆ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ◆
■ ■ ■ ■ ■ ◆ ■ ■
■ ■ ◆ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ◆ ■
■ ◆ ■ ■ ■ ■ ■ ■
■ ■ ■ ◆ ■ ■ ■ ■

◆ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ◆ ■ ■
■ ■ ■ ■ ■ ■ ■ ◆
■ ■ ◆ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ◆ ■
■ ■ ■ ◆ ■ ■ ■ ■
■ ◆ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ◆ ■ ■ ■

◆ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ◆ ■
■ ■ ■ ◆ ■ ■ ■ ■
■ ■ ■ ■ ■ ◆ ■ ■
■ ■ ■ ■ ■ ■ ■ ◆
■ ◆ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ◆ ■ ■ ■
■ ■ ◆ ■ ■ ■ ■ ■

◆ ■ ■ ■ ■ ■ ■ ■
■ ■ ■ ■ ■ ■ ◆ ■
■ ■ ■ ■ ◆ ■ ■ ■
■ ■ ■ ■ ■ ■ ■ ◆
■ ◆ ■ ■ ■ ■ ■ ■
■ ■ ■ ◆ ■ ■ ■ ■
■ ■ ■ ■ ■ ◆ ■ ■
■ ■ ◆ ■ ■ ■ ■ ■

4
参考技术A 此程序可解决N后问题,但输出效果没有上面的好

#include<iostream.h>

const int N = 20;

void main()
cout<<"n后问题\n\n";
int n, m, good, col[N+1], a[N+1], b[2*N+1], c[2*N+1], j;
cout<<"n = "; cin>>n;
for(j = 0; j <= n; j++) a[j] = 1;
for(j = 0; j <= 2*n; j++) b[j] = c[j] = 1;
m = col[1] = good = 1; col[0]=0;
do
if(good)
if(m == n)
cout<<"\n 列 行\n";
for(j = 1; j <= n; j++)
cout<<" "<<j<<" "<<col[j]<<endl;;
while(col[m] == n)
m--;
a[col[m]] = b[m+col[m]] = c[n+m-col[m]] = 1;

col[m]++;

else // m==n
a[col[m]] = b[m+col[m]] = c[n+m-col[m]] = 0;
col[++m] = 1;


else //good
while(col[m] == n)
m--;
a[col[m]] = b[m+col[m]] = c[n+m-col[m]] = 1;

col[m]++;
// end good
good = a[col[m]] && b[m+col[m]] && c[n+m-col[m]];
while(m);
cin>>n;
参考技术B #include<stdio.h>

int q[20];
void Queens(int,int);
int Place(int,int);
void print(int);

int main()

int n;

printf("您要求的是几皇后问题?\n");
scanf("%d",&n);
Queens(1,n);

system("pause");
return 0;


void Queens(int k,int n)

int i;
if(n<k)
print(n);
else
for(i=1;i<=n;i++)
if(Place(i,k)==1)
q[k]=i;
Queens(k+1,n);




int Place(int i,int k)

int j=1;
while(j<k)
if((q[j]==i)||abs(q[j]-i)==abs(j-k))
return 0;
j++;

return 1;


void print(int n)

int i;

for(i=1;i<=n;i++)
printf("<%d,%d>\t",i,q[i]);

printf("\n");

求解八皇后问题的退火算法

这个算法收敛速度还算满意。此算法可以计算n皇后问题,只需要将n改为相应整数即可!

主程序:

clear;
clc;
%%
%八皇后问题,8X8的棋盘上,放置8个皇后,使之两两都不能攻击

%使用退火算法计算

%初始的状态,随机在棋盘上放置8个皇后,每列放一个,使每一行都不能攻击
n = 8; %8皇后
%%
%产生一个随机的状态
state = randperm(n);

%%
%计算当前状态的h函数值(与目标状态的差距,h越大,差距越大。h=0代表此状态即为目标状态)
h = fun_c(state);
disp(state);
disp([‘初始状态的h为‘,num2str(h)]);
%%

    %用退火算法从初始状态产生新的状态
   
    %从时间1开始,t代表时间
    t = 1;
    t_max = 1e5;  %允许循环的最大时间
    plt = zeros(3,t_max);
    
    while t < t_max && h ~=0
        %交换现在状态中的任意两个数
        i_rand = 1;
        j_rand = 1;
        while i_rand == j_rand
            i_rand = randi(n);
            j_rand = randi(n);
        end
        state_tmp = state;
        tmp = state_tmp(i_rand);
        state_tmp(i_rand) = state_tmp(j_rand);
        state_tmp(j_rand) = tmp;
        
        h_tmp = fun_c(state_tmp);
        if h_tmp <= h
            state = state_tmp;
            h = h_tmp;
         elseif h_tmp > h
             T = fun_temp(t);  % 当前温度
             %温度越高,增加的能量越低,此状态的概率越大
             p = exp(-(h_tmp-h)*500/T); 
             %有一定的概率接受此状态
             if p > rand(1)
                 state = state_tmp;
                 h = h_tmp;
             end
        end
       
         plt(1,t) = t;
         plt(2,t) = fun_temp(t);
         plt(3,t) = h;
         t = t + 1;
     
    end
     figure(1);
     axis auto;
     plot(plt(1,1:(t-1)),plt(2,1:(t-1)),‘b‘); %t VS T
     hold on;
     plot(plt(1,1:(t-1)),100*plt(3,1:(t-1)),‘r‘); %t VS h
     hold off;

%%
    if h == 0
        disp(‘退火算法成功‘);
    else
        disp(‘退火算法失败‘);
    end
    disp([‘经历的时间为‘,num2str(t)]);
    disp([‘最终状态的h为‘,num2str(h)]);
    disp(state);
    %将state转换成nXn矩阵
    state_full = zeros(n,n);
    for i=1:n
        for j=1:n
            if j == state(i)
                state_full(i,j) = 1;
            end
        end
    end
 %%
    %显示最终的状态
    disp(state_full);

 各子函数

function [h] = fun_c(state)
    %根据一个状态,评价它的代价函数
    h = 0;
    n = length(state);    
%%
    %每列的状态,看有多少个能互相攻击,每两两攻击算一次
    for i=1:n
        count = length(find(state == i));
        if count > 1;
            h = h + nchoosek(count,2);
        end
    end
   %%
    %将state转换成nXn矩阵
    state_full = zeros(n,n);
    for i=1:n
        for j=1:n
            if j == state(i)
                state_full(i,j) = 1;
            end
        end
    end
    %%
    %每个左斜对角的状态,看有多少个能互相攻击,每两两攻击算一次
    i=1;
    j=1;
    add = 0;
    while i<n+1 && j<n+1 && i>0 && j>0 
        %计算左斜对角每条线有多少个皇后
        count = fun_calc_left(i,j,n,state_full);
            if count > 1;
                h = h + nchoosek(count,2);
            end
            
            if add == 0;
                j = j + 1;
            elseif add == 1; 
                i = i + 1;
            end
            
        add = ~add;
    end
    
    %%
    %每个右斜对角的状态,看有多少个能互相攻击,每两两攻击算一次
    i=1;
    j=n;
    add = 0;
    while i<n+1 && j<n+1 && i>0 && j>0
        %计算右斜对角有多少个皇后
        count = fun_calc_right(i,j,n,state_full);
            if count > 1;
                h = h + nchoosek(count,2);
            end
            
            if add == 0;
                j = j - 1;
            elseif add == 1; 
                i = i + 1;
            end
            
        add = ~add;
    end
    
end
    

 

function count = fun_calc_left(i,j,n,state_full)
%%   
%统计i,j 点,左下角
    count = 0;
    i_l = i;
    i_r = i;
    j_l = j;
    j_r = j;
    while i_l>0 && j_l>0 && i_l<n+1 && j_l<n+1
        count = count + state_full(i_l,j_l);
        i_l = i_l + 1;
        j_l = j_l - 1;
    end
%%
   %右上角的个数
    while i_r>0 && j_r>0 && i_r<n+1 && j_r<n+1
        count = count + state_full(i_r,j_r);
        i_r = i_r - 1;
        j_r = j_r + 1;
    end
    %%
    %被重复加的,减去
    count = count - state_full(i,j);
end

 

function count = fun_calc_right(i,j,n,state_full)
%%   
%统计i,j 点,左上角
    count = 0;
    i_l = i;
    i_r = i;
    j_l = j;
    j_r = j;
    while i_l>0 && j_l>0 && i_l<n+1 && j_l<n+1
        count = count + state_full(i_l,j_l);
        i_l = i_l - 1;
        j_l = j_l - 1;
    end
%%
   %右下角的个数
    while i_r>0 && j_r>0 && i_r<n+1 && j_r<n+1
        count = count + state_full(i_r,j_r);
        i_r = i_r + 1;
        j_r = j_r + 1;
    end
    %%
    %被重复加的,减去
    count = count - state_full(i,j);
end

 

function T = fun_temp(t)
%给定退火的时间和速率,t为时间,T为温度

    if t<= 50
        T = 1000;
    elseif t>50 && t<1000
        T = 1000 -  ( t - 50 )*100/95;
    else 
        T = 1e-3;
    end


end

 


 

以上是关于八皇后问题求解的C语言程序的实现的主要内容,如果未能解决你的问题,请参考以下文章

八皇后问题

八皇后问题算法详解

八皇后问题遗传算法实现(python版)

八皇后问题求解java(回溯算法)

求解八皇后问题的退火算法

什麽是“八皇后问题”?