N皇后问题 (回溯+打表)

http://acm.hdu.edu.cn/showproblem.php?pid=2553

第一种方法,需打表,否则超时

#pragma warning (disable:4786)  
#include<iostream>
using namespace std;
int used_column[12];                  //标记列是否被用过
int used_Ldia[102],used_Rdia[102];    //标记对角线是否被用过
int n,cc,result;

//返回该元素所在左对角线最左上角的元素坐标
int  getLIndex ( int row, int column ){

	if( row > column ){
		return ( row - column ) * n;
	}
	else {
		return ( column - row );
	}
}

//返回该元素所在右对角线最右上角的元素坐标
int getRIndex( int row, int column ){
	if( row + column > n - 1 ){
		return ( row + column - n + 1 ) * n + n -1;
	}
	else {
		return ( row + column );
	}
}

//深搜
void DFS( int row ){

	int i;
	for( i = 0; i < n; i ++ ){
		int l_index = getLIndex ( row, i ); 
		int r_index = getRIndex ( row, i ); 

		//所在列、所在左右对角线都未被使用时,可尝试在该处放置皇后
		if( used_column[i] == 0 && used_Ldia[l_index] ==0 && used_Rdia[r_index] ==0 ){
			cc ++;                  //标记当前总共放置的皇后数
			if( cc == n )
				result ++;          //倘若当前总共放置的皇后数达到了n,则放置策略数+1
			else{
				used_column[i] = 1;
				used_Ldia[l_index] = 1;
				used_Rdia[r_index] = 1;
				DFS( row + 1 );	    //递归求解

				//恢复状态
				used_column[i] = 0;
				used_Ldia[l_index] = 0;
				used_Rdia[r_index] = 0;
			}
			//恢复状态
			cc --;
		}
	}

}
			
int main(){
    int i,j, f[11];
	//打表,否则超时
	for( n = 1; n <= 10; n ++ ){
		memset( used_column, 0, sizeof( used_column ) );
		memset( used_Ldia, 0, sizeof( used_Ldia ) );
        memset( used_Rdia, 0, sizeof( used_Rdia ) );
		cc = result = 0;
		DFS(0);
		f[n] = result;
	}

    while( scanf( "%d", &n ) &&  n ){             
        printf( "%d\n", f[n] );
    }
	return 0;
}


第二种方法,当当当当~~华丽丽的 cheat,当超时时,运行代码,得出结果,然后用以下方法...

#pragma warning (disable:4786)  
#include<iostream>
using namespace std;
			
int main(){
    int f[11] = {0,1,0,0,2,10,4,40,92,352,724};
	int n;
    while( scanf( "%d", &n ) &&  n ){

        printf( "%d\n", f[n]);
    }
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值