皇后问题最快的解法(C语言)八皇后、十六皇后时间在毫秒级

//皇后问题最快的解法(C语言)八皇后、十六皇后时间在毫秒级
#include <windows.h>
# include<stdio.h>
# include<stdlib.h>
# include<time.h>
#define O  134775813
// TODO (xubo18056052430#1#): PB10210016  徐波

LARGE_INTEGER lv,lv1,lv2,lv3,lv4;
double totaltime,secondsPerTick;
int step;

/***********************************************************************************************/
int dn(int n)          //分组,根据经验值产生,网搜得到--取下列值是比较好,返回不同的值对实验结果影响很大
{
    if (n < 100)
		return n;
	else if (n < 1000)
		return 40;
	else if (n < 10000)
		return 60;
	else if (n < 100000)
		return 90;
	else
		return 150;
}
/***********************************************************************************************/

/***********************************************************************************************/
int rand1 = (unsigned)time(NULL);        //rand1产生随机数
int rand2(int range)                     //rand1线性同余随机数产生器
{
	unsigned int x = 0x7fffffff, m, c = 1, a =O;
	m = x + 1;
	rand1 = (rand1 * a + 1)%m;
	double r =(double) rand1 / x;
	int r2 =  (int)(r * range);
	return r2;
}
/***********************************************************************************************/

/***********************************************************************************************/
void swap(int &a, int &b){                                            //交换两值
	int c;
	c = a;a = b;b = c;
}
/***********************************************************************************************/

/***********************************************************************************************/
int chongtu(int n, int line1[], int line2[]){                      //冲突
	int xubo = 0;
	for(int i = 0; i < n + n; i ++){
		if(line1[i] > 1){xubo = xubo + (line1[i] * (line1[i] - 1)) / 2;}
		if(line2[i] > 1){xubo = xubo + (line2[i] * (line2[i] - 1)) / 2;}
	}
	return xubo;
}
/***********************************************************************************************/

/***********************************************************************************************/
int improve(int i, int j, int n, int q[], int line1[], int line2[])  //判断q[i]和q[j])交换后冲突的个数是否会减少
{
	int xubo = 0;
	xubo = xubo + (1 - line1[i + q[i]]);
	xubo = xubo + (1 - line2[i - q[i] + n - 1]);
	xubo = xubo + (1 - line1[j + q[j]]);
	xubo = xubo + (1 - line2[j - q[j] + n - 1]);

	xubo = xubo + line1[i + q[j]];
	xubo = xubo + line2[i - q[j] + n - 1];
	xubo = xubo + line1[j + q[i]];
	xubo = xubo + line2[j - q[i] + n - 1];

	if(i + q[i] == j + q[j] || i - q[i] == j - q[j])
		xubo = xubo + 2;
	return xubo;
}
/***********************************************************************************************/

/***********************************************************************************************/
void csh(int n, int m, int q[], int line1[], int line2[])
{
	int i, end, rand3;
	bool *l1 = (bool *)malloc((n + n) * sizeof(bool));
	bool *l2 = (bool *)malloc((n + n) * sizeof(bool));
	for(i = 0; i < n; i ++)
	{
		q[i] = i;
		line1[i] = 0;
		line2[i] = 0;
		l1[i] = false;
		l2[i] = false;
	}
	for(i = n; i < n + n; i ++)
	{
		line1[i] = 0;
		line2[i] = 0;
		l1[i] = false;
		l2[i] = false;
	}

	for(i = 0, end = n; i < m; i ++, end --)   //初始化(0 ~ m - 1);前m行不会此时不会产生冲突
	{                                          //初始化后横竖无冲突,只要保证两斜线无冲突即可
		do
		{
			rand3 = i + rand2(end);
		}while(l1[i + q[rand3]] || l2[i - q[rand3] + n - 1]);

		swap(q[i], q[rand3]);
		line1[i + q[i]] ++;
		line2[i - q[i] + n - 1] ++;
		l1[i + q[i]] = true;
		l2[i - q[i] + n - 1] = true;
	}

	for(i = m, end = n - m; i < n; i ++, end--)                      //初始化line
	{
		rand3 = i + rand2(end);

		swap(q[i], q[rand3]);
		line1[i + q[i]] ++;
		line2[i - q[i] + n - 1] ++;
	}

	free(l1);
	free(l2);
}
/***********************************************************************************************/

/***********************************************************************************************/
void work(int n, int m, int q[])
{
    QueryPerformanceFrequency( &lv );
    secondsPerTick = 1000000.0 / lv.QuadPart;
	int temp, reduce, i, j;
	step = 0;
	int *line1 = (int *)malloc((n + n) * sizeof(int));
    int *line2 = (int *)malloc((n + n) * sizeof(int));
    QueryPerformanceCounter( &lv3 );
	csh(n, m, q, line1, line2);
	QueryPerformanceCounter( &lv4 );
	totaltime = secondsPerTick * (lv4.QuadPart-lv3.QuadPart);
	printf("\n初始化时间为:%e  s ", totaltime/1000000); //初始化时间
	temp = chongtu(n, line1, line2);
	//printf("冲突次数= %d\n", temp);

	while(temp > 0){
		reduce = 0;
		for(i = m; i < n; i ++){
			if(line1[i + q[i]] == 1 && line2[i - q[i] + n - 1] == 1)
				continue;
			else{
				for(j = 0; j < n; j ++){
					if(i != j){
						reduce = improve(i, j, n, q, line1, line2);
						if(reduce < 0)
							break;
					}
				}
				if(reduce < 0)   //可交换q[i]和q[j],使总的冲突减少
					break;
			}
		}
		if(reduce < 0){
			step ++;
			line1[i + q[i]] --;
			line2[i - q[i] + n - 1] --;
			line1[j + q[j]] --;
			line2[j - q[j] + n - 1] --;

			swap(q[i], q[j]);

			line1[i + q[i]] ++;
			line2[i - q[i] + n - 1] ++;
			line1[j + q[j]] ++;
			line2[j - q[j] + n - 1] ++;

			temp = temp + reduce;
		}
		else
		{
	        csh(n, m, q, line1, line2);
             temp = chongtu(n, line1, line2);

		}
	}
}
/***********************************************************************************************/

/***********************************************************************************************/
size_t **NQueen(size_t q_xubober)      //实验要求size_t **NQueen(size_t Queen_xubober)
{
    LARGE_INTEGER lv,lv1,lv2;
    double totaltime,secondsPerTick;
    QueryPerformanceFrequency( &lv );
    secondsPerTick = 1000000.0 / lv.QuadPart;
	unsigned int **ee = (unsigned int **)malloc(4 * sizeof(unsigned int *)), loop = 3, i, j;

	for(i = 1; i < 4; i ++)
		ee[i] = (unsigned int *)malloc((q_xubober + 1) * sizeof(unsigned int));
	int *q = (int *)malloc(q_xubober * sizeof(int));
	int m = q_xubober - dn(q_xubober);
	printf("\n问题大小N= %d  m= %d\n*************************************************************************\n", q_xubober, m);

    for(i = 1; i < 4; i ++){
        QueryPerformanceCounter( &lv1 );
		work(q_xubober, m, q);
		QueryPerformanceCounter( &lv2 );
		totaltime = secondsPerTick * (lv2.QuadPart-lv1.QuadPart);
	    printf("第%d次成功运行时间= %e s \n", i, totaltime/1000000);
        printf("\n*************************************************************************\n");
		for(j = 0; j < q_xubober; j ++)
			ee[i][j + 1] = q[j] + 1;
	}
	return ee;
}
/***********************************************************************************************/

/***********************************************************************************************/
int main(){
	unsigned int i, j, k = 0, **ee = NULL;
	int n;
	printf("请输入皇后问题N的大小:\n");
	scanf("%d", &n);
	printf("\n————————————————运行结果————————————————\n");
	if(n<=3){
	    printf("\错误!没有解!");
	    exit(1);                       //输入小于4的数报错跳出
	}
	if(n>=1000000000003){
	    printf("\错误!没有解!");
	    exit(1);                       //输入大于的数报错跳出
	}
	ee = NQueen(n);
   if(n<=100){                       //如果输入的n小于等于100,者输出皇后摆放位置序列,否者不输出,因为n大序列长
   for(i = 1; i <=3; i++)            //输出三个满足问题要求的皇后摆放位置序列try[1..3][1…n]。
	{
	    printf("\n\n第%d组解皇后摆放的位置序列位:\n",i);
		for(int j = 1; j < n + 1; j ++){
			for(k = 1; k < n + 1; k ++){
				if(k ==ee[i][j]){
					//printf("%d ",k);    //只输出列
					printf("(%d,%d) ",j,k);}  //输出行和列,第i个皇后摆放在(i,try[i])

			}
        }
        }
	}
    printf("\n\n————————————————运行结果————————————————\n\n\n");
	system("pause");
	return 0;

}
/***********************************************************************************************/
// TODO (xubo18056052430#1#): PB10210016  徐波

你可能感兴趣的:(皇后问题最快的解法C语言,八皇后十六皇后时间在毫秒级)