签到

06月21日
尚未签到

共有回帖数 0

    懂得生活的人

    等级:
    最近看到又有不少人在讨论八皇后问题,乃至N皇后问题,我就把去年的作业贴出来给大家探讨下吧。

    本文主要内容:用回溯和局部搜索方法,实现求解N皇后问题的程序,并且比较耗费时间

    先给出两种方法的耗费时间比较:
    方法棋盘大小 15 20 27 29 30 100 200 500 1000
    回溯法耗时(ms) 0 47 125 409 15719
    局部搜索法耗时(ms) 0 0 0 0 15 100 1000 12000 40000

    以下是两种方法的程序:
    回溯法程序:
    #includeiostream.h
    #includestring.h
    #includetime.h

    #define size 100
    int board[size];
    int ver[size];
    int ru[size*2];//右上
    int rd[size*2];//右下
    int n,find; int rec[size];

    //回溯搜索
    void dfs(int t)
    {
    int i;
    if(find) return;
    if(t==n)
    {
    find=1;
    for(i=0;in;i++)
    {
    rec=board;
    }
    return;
    }
    for(i=0;in;i++)
    {
    if(ver==1) continue;
    if(ru[i-t+n]==1) continue;
    if(rd[i+t]==1) continue;
    ver=1;
    ru[i-t+n]=1;
    rd[i+t]=1;
    board[t]=i;
    dfs(t+1);
    rd[i+t]=0;
    ru[i-t+n]=0;
    ver=0;
    }
    return;
    }

    int main()
    {
    int i,j,t1,t2;
    cout"输入棋盘大小:";
    cinn;
    t1=clock();
    find=0; memset(ver,0,sizeof(ver));
    memset(ru,0,sizeof(ru)); memset(rd,0,sizeof(rd));
    dfs(0);
    t2=clock();
    if(find)
    for(i=0;in;i++)
    {
    for(j=0;jn;j++)
    {
    if(rec==j) cout'X';
    else cout'+';
    }
    coutendl;
    }
    else
    cout"Can't find!n";
    cout"耗费时间:"t2-t1"msn";
    return 0;
    }

    局部搜索程序:
    #includeiostream.h
    #includestring.h
    #includestdlib.h
    #includetime.h

    #define size 2000
    int board[size];//记录棋盘状况的数组

    //记录冲突的数组
    int ru[size*2];//右上
    int rd[size*2];//右下

    int recran[size];
    int n; int rec[size];

    int f()
    {//计算冲突的函数
    int i,r=0;
    memset(ru,0,sizeof(ru));
    memset(rd,0,sizeof(rd));
    for(i=0;in;i++)
    {
    ru[board-i+n]++;
    rd[board+i]++;
    }
    for(i=0;i2*n;i++)
    {
    if(ru1) r+=ru-1;
    if(rd1) r+=rd-1;
    }
    return r;
    }

    //生成x个不重复的随机数,放入board数组
    void randgen(int x)
    {
    int i,temp;
    memset(recran,0,sizeof(int)*(n+1));
    for(i=0;in;i++)
    {
    do
    {
    temp=rand()%x;
    }
    while(recran[temp]==1);
    board=temp;
    recran[temp]=1;
    }
    }

    int main()
    {
    srand((unsigned) time(NULL));

    int i,j,temp,now,t1,t2,fnow;
    cout"输入棋盘大小:";
    cinn;
    coutendl;
    t1=clock();
    //find=0;
    //局部搜索部分
    while(1)
    {
    randgen(n);
    now=f();
    next: if(now==0) goto over;
    for(i=0;in-1;i++)
    {
    for(j=i+1;jn;j++)
    {
    temp=board; board=board[j]; board[j]=temp;
    fnow=f();
    if(fnownow)
    {
    now=fnow;
    goto next;
    }
    temp=board; board=board[j]; board[j]=temp;
    }
    }
    }
    over:
    t2=clock();
    /*for(i=0;in;i++)
    {
    for(j=0;jn;j++)
    {
    if(board==j) cout'X';
    else cout'+';
    }
    coutendl;
    }*/
    cout"耗费时间:"t2-t1"msn";
    return 0;
    }

    经检验,在有解并且时间允许的情况下,两程序均可以找到一组正确解。
    棋盘大小在30以上,回溯法在有限时间内基本无法找到解,而棋盘大小直到1000,局部搜索法仍能找到正确��


    楼主 2016-02-19 16:44 回复

共有回帖数 0
  • 回 帖
  • 表情 图片 视频
  • 发表

登录直线网账号

Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号 意见反馈 | 关于直线 | 版权声明 | 会员须知