码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 524 - Prime Ring Problem

时间:2014-07-03 17:45:19      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:blog   数据   os   2014   for   io   

题目:把1-n,连续的放到一个环里,使相邻的数字和为素数,输出所有结果。

分析:搜索+剪枝。如果裸搜,用dancing-links那种拆装的链表,应该差不多满足16的数据量。

            这里利用一个性质进行剪枝:相邻的数字一定是奇偶性不同的数字。

            (如果上述假设不成立,则存在相邻的奇数或偶数,那么他们的和一定是大于2的偶数,不是素数)

            根据上面的假设,还有一条推论:只有n为偶数时才有解。

            (n为奇数,一直至少有一对奇数相邻,同上,矛盾(鸽巢原理))

            因此,每次搜索的数据其实是n/2,时间复杂度为O((n/2)!* 2^(n/2));

            打表计算,查询输出即可。

说明:注意题目没说,每组输出间有一个空行。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

int prime[32];
int visit[18];
int queue[18];
int size[18];
int ans[18][100000][18];

void dfs( int d, int n )
{
	if ( d == n && !prime[queue[d-1]+1] ) {
		for ( int i = 1 ; i < n ; ++ i )
			ans[n][size[n]][i] = queue[i];
		size[n] ++;
		return;
	}
	for ( int i = d%2+1; i <= n ; i += 2 )
		if ( !visit[i] && !prime[i+queue[d-1]] ) {
			visit[i] = 1;
			queue[d] = i;
			dfs( d+1, n );
			visit[i] = 0;
		}
}

int main()
{
	memset( prime, 0, sizeof(prime) );
	prime[0] = prime[1] = 1;
	for ( int i = 2 ; i < 32 ; ++ i ) 
		if ( !prime[i] )
			for ( int j = 2*i ; j < 32 ; j += i )
				prime[j] = 1;
	
	memset( visit, 0, sizeof(visit) );
	visit[1] = 1;
	queue[0] = 1;
	memset( size, 0, sizeof(size) );
	for ( int i = 2 ; i <= 16 ; i += 2 )
		dfs( 1, i );
	
	int n,m,t = 0;
	while ( ~scanf("%d",&n) ) {
		if ( t ++ ) printf("\n");
		printf("Case %d:\n",t);
		m = size[n];
		for ( int i = 0 ; i < m ; ++ i ) {
			printf("1");
			for ( int j = 1 ; j < n ; ++ j )
				printf(" %d",ans[n][i][j]);
			printf("\n");
		}
	}
	return 0;
}

UVa 524 - Prime Ring Problem,布布扣,bubuko.com

UVa 524 - Prime Ring Problem

标签:blog   数据   os   2014   for   io   

原文地址:http://blog.csdn.net/mobius_strip/article/details/36624421

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!