• hdu2553N皇后问题


    N皇后问题

    打表 

     #include<iostream>
     using namespace std;
     int a[11]={0,1,0,0,2,10,4,40,92,352,724};
     int main()
     {
         int n;
         while(scanf("%d",&n)>0&&n)
         {
             printf("%d\n",a[n]);
         }
         return 0;
     }


    /************************************************************
     * Author        : rudolf
     * Last modified : 2013-04-23 15:27
     * Filename      : caogao.cpp
     * Description   :
     * *********************************************************/
    #include <stdio.h>
    #include <iostream>
    #include<string.h>
    using namespace std;
    int map[20],a[20],hang[20],n,cnt;
    void DFS(int num)
    {
    	int i,j,flag;
    	if(num==n+1)//到n也成立了才会搜索n+1
    	{
    		cnt++;return;
    	}
    	for(i=1;i<=n;i++)
    		if(!hang[i])//不在同一行
    		{
    			flag=1;map[num]=i;//第num列第i行放第num个皇后
    			for(j=1;j<num;j++)
    				if((map[num]-num==map[j]-j)||(map[num]+num==map[j]+j))//判断是否在对角线上
    				{	
    					flag=0;
    					break;
    				}
    				if(flag)
    				{
    					hang[i]=1;
    					DFS(num+1);//递归调用
    					hang[i]=0;//回溯
    				}
    		}
    }
    int main()
    {
    	int i,m;
    	for(i=1;i<11;i++)//打表列出N个皇后对应几种方法
    	{
    		memset(map,0,sizeof(map));
    		memset(hang,0,sizeof(hang));
    		n=i;cnt=0;
    		DFS(1);
    		a[i]=cnt;
    	}
    	while(cin>>m&&m!=0)
    		cout<<a[m]<<endl;
    	return 0;
    }


    /**
    n皇后问题,由于N 是小于等于10的正整数,
    所以可以使用打表的方法把前十中情况全
    部找出来存起来然后每次输入时不用重新
    的计算了。
    */
    #include <stdio.h>
    
    #define NUMS 10
    /*输入的数字1---10*/
    int N;
    /*棋盘*/
    int chessboard[11][11];
    /* 用来记录拜访数目 */
    int cal;
    
    /*
    检查皇后放置此行此列是否可以,可以返回1,不可以返回0
    此递归是一行一行找的,K是棋盘的长度
    */
    int dfs_check(int row,int column,int k)
    {
        /* 说明已经到了棋盘的界外,前边都符合了 */
        if(row>k)
        {
            cal++;
            return 1;
        }
        /* 正上方是否有皇后*/
        for(int i = 1; i < row; i++)
            /* 如果有皇后则返回不能放置这里返回0*/
        if(chessboard[i][column] == 1)
        return 0;
    
        /* 左右上方45度角检查是否可以*/
        /* 左上方*/
        for(int i=row-1,j=column-1;i>0&&j>0;i--,j--)
        if(chessboard[i][j] == 1)
        return 0;
        /* 右上方*/
        for(int i=row-1,j=column+1;i>0&&j<=k;i--,j++)
        if(chessboard[i][j] == 1)
        return 0;
        /*标记这个位置成功了*/
        chessboard[row][column] = 1;
    
        /*进行下一行搜索*/
        for(int i=1;i<=k;i++)
        if(dfs_check(row+1,i,k)==1)
        break;
    
        chessboard[row][column] = 0;
        return 0;
    }
    
    
    int main()
    {
        int i,j,k;
        int count[11];
        /*打表*/
        for(k=1;k<=NUMS;k++)
        {
            count[k] = 0;
            cal = 0;
            /*首先将棋盘初始化全部置为0*/
            for(i=0;i<=NUMS;i++)
            for(j=0;j<=NUMS;j++)
            chessboard[i][j]=0;
            for(i=1;i<=k;i++)
            dfs_check(1,i,k);
            count[k] = cal;
        }
    
        while(scanf("%d",&N)!=EOF&&N!=0)
        printf("%d\n",count[N]);
        return 0;
    }



    回溯法(转)能力有限,理解不了他的代码http://blog.csdn.net/alongela/article/details/6755770

    用回溯法就可以解决,设皇后的编号依次为1,2,……,n,则可以认为第i个皇后必须摆放在第i行,然后枚举第一个皇后的位置进行回溯,若某一次发现某个皇后无法找到摆放位置则直接返回,如果所有皇后都可以找到摆放位置,则说明存在一种摆法满足要求,统计有多少种摆法即可。


    此题n<=10,测试数据中会有大量重复数据,因此要保存答案,遇到曾经计算过的n直接输出即可,否则可能会超时。

    #include<iostream>
    using namespace std;
    int n;
    int x[100];
    int ans[11];
    bool Place(int k)
    {
    	int i = 1;
    	while (i<k)
    	{
    		if (x[i]==x[k] || abs(x[i]-x[k])==abs(i-k))	return false;
    		i++;
    	}
    	return true;
    }
    int main()
    {
    	int k, cnt;
    	memset(ans, 0, sizeof(ans));
    	while (scanf("%d", &n)!=EOF && n!=0)
    	{
    		if (ans[n]>0) 
    		{
    			printf("%d\n", ans[n]);
    			continue;
    		}
    		x[1] = 0;
    		k = 1, cnt = 0;
    		while (k>0)
    		{
    			x[k]++;
    			while (x[k]<=n && !Place(k))
    			{
    				x[k]++;
    			}
    			if (x[k]<=n)
    			{
    				if (k==n)
    				{
    					cnt++;
    				}
    				else 
    				{
    					k++;
    					x[k] = 0;
    				}
    			}
    			else k--;
    		}
    		ans[n] = cnt;
    		printf("%d\n", cnt);
    	}
    	return 0;
    }
    

    dfs

    #include<iostream>
     #include<math.h>
     using namespace std;
     int s[12][12],n,count;
     int panduan(int h,int l)
     {
         for(int i=0;i<n;i++)           //判断列
         {
             if(s[i][l]==0||i==h)
                 continue;
             else
                 return 0;
         }
         for(i=0;i<n;i++)            //判断行
         {
             if(s[h][i]==0||i==l)
                 continue;
             else
                 return 0;
         }
         for(i=0;i<n;i++)          //判断成45度的线
         {
             for(int j=0;j<n;j++)
             {
                 if(s[i][j]==0||(i==h&&j==l))
                     continue;
                 else
                 {
                     if(abs(h-i)==abs(l-j))          //只要y=kx+b中abs(k)==1,说明成了45度的线
                         return 0;
                 }
             }
         }
         return 1;
     }
     void dfs(int num,int f)
     {
         int i,j;
         if(num==n*n)
         {
             if(f==0)
                 count++;
             return;
         }
         if(num>n*n)return;
         i=num/n;
         j=num%n;
         if(s[i][j]==0&&panduan(i,j))
         {
             s[i][j]=1;
             dfs(num+1,f-1);
             s[i][j]=0;
         }
         dfs(num+1,f);
     }
     int main()
     {
         while(scanf("%d",&n)>0&&n)
         {
             memset(s,0,sizeof(s));
             count=0;
             dfs(0,n);
             //printf("\n\n");
             printf("%d\n",count);
         }
         return 0;
     }


  • 相关阅读:
    laravel路由和MVC
    laravel目录介绍
    laravel下载安装
    Mac 程序员的十种武器
    Python中列表的copy方法
    Ubuntu 安装vim失败解决
    Linux userAdd 增加用户如果没有配置文件情况解决
    Ubuntu 软件管理
    awk工具详解
    httpsClient
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3038653.html
Copyright © 2020-2023  润新知