为防止广告,目前nocow只有登录用户能够创建新页面。如要创建页面请先登录/注册(新用户需要等待1个小时才能正常使用该功能)。

Sgu/157

来自NOCOW
< Sgu
跳转到: 导航, 搜索

By mx 此题n的范围很小,可以打表,但打个三两个小时也不是办法,用以下方法可以几秒钟至十几秒钟出结果(本地测n=13时11秒多出结果)。 注意到每种可行状态都可以由另一种可行状态以以下的变换而得出: ①找到给定范围内的Ai,使得Ai=Ai-1 +1。 ②将空位与Ai交换。 (其实就是题目中的变换的逆变换) 所以只要从终态开始,不断以上述变换扩展,每次扩展得到的值必为可行方案。容易证明每种可行状态只有一种变换方案达到终态(因为每次只有一种移动方法),反过来可知,每种状态只会被扩展一次,所以连判重都不用。 下列程序当n≥10时打表,n<10时搜索。搜索本身就可以用来打表。

//by mx
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 13
#define MAX(x,y) ((x)>(y)?(x):(y))
#define ABS(x) (MAX(x,-(x)))
#define MIN(x,y) ((x)<(y)?(x):(y))
#define oo 1e9
#define R return
long n,a[MAXN+5]={0},ans=0,place;
void init()
{
	long i;
	scanf("%ld",&n);
	if (n==13) ans=118515434;
	else if (n==12) ans=12966093;
	else if (n==11) ans=1548222;
	else if (n==10) ans=203173;
	place=n;
	for (i=1;i<=n;i++)
	    a[i]=i;
	R;
}
void solve()
{
	long i,t=place;
	ans++;
	for (i=1;i<=n;i++)
	{
		if (i!=place&&a[i]==a[i-1]+1)
		{
			a[place]=a[i];
			a[i]=n;
			place=i;
			solve();
			place=t;
			a[i]=a[place];
			a[place]=n;
		}
	}
	R;
}
void output()
{
	printf("%ld\n",ans);
	R;
}
int main()
{
	init();
	if (n<10) solve();
	output();
	R 0;
}
/by Logic
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=20,N=14;
int n,p[maxn],ans=0;
void dfs(int emp)
{
	int i,j,p0[maxn],z=0;
	memcpy(p0,p,sizeof(p));
	//for(i=1;i<=N;i++) printf("%d ",p[i]); printf("\n");
	ans++;
	for(i=N-n;i<N;i++)
	{
		if(p[i]==p[i+1]-1)
			swap(p[i+1],p[emp]),dfs(i+1);
		memcpy(p,p0,sizeof(p));
	}
}
int main()
{
	int i;
	for(i=1;i<N;i++)
		p[i]=i;
	p[N]=0;
	scanf("%d",&n);
	if(n==11) ans=1548222;
	else if(n==12) ans=12966093;
	else if(n==13) ans=118515434;
	else dfs(14);
	printf("%d",ans);
	return 0;
}
个人工具