hihocoder 北京网赛 boxs #1233 : Boxes

根据汉诺塔的特点找到保存状态的最简方式。懂得hash的真谛才能ac qaq

首先从有序状态可以推出所有有解状态。大体是给每个不同的数字以不同的模,根据他们的位置分别哈希,加起来作为该种状态的哈希值。

这样可以根据这个哈希值取得各个数字的位置,得到当前情况。打表出各种移动的所需要的代价,即可转移到下一个状态

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=20000008;
int mp7[maxn];
int mp6[maxn>>1];
int mp5[maxn>>2];
int mp4[maxn>>3];
int mp3[maxn>>4];
int dp[10][10];
void bfs(int ha,int mp[],int mod)
{
	queue<int>	q;
	queue<int>	p;
	q.push(ha);
	p.push(0);
	mp[ha]=0;
	int i,a[10],b[10];
	int x,y,sx,idx,nx,ny;
	while(!q.empty())
	{
		x=q.front();q.pop();
		y=p.front();p.pop();
		 sx=x;idx=0;
		for(i=1;i<=mod;i++)
		{
			a[i]=sx%mod;
			sx/=mod;
		}
		memset(b,INF,sizeof(b));
		for(i=1;i<=mod;i++)
			if(b[a[i]+1]>i)
				b[a[i]+1]=i;
		b[0]=0;b[mod+1]=0;	
		for(i=1;i<=mod;i++)
		{
			if(b[i]==INF)	continue;
			if(b[i]<b[i-1])
			{
				nx=x-dp[mod][b[i]];
				if(mp[nx]==-1)
				{
					ny=y+1;
					mp[nx]=ny;
					q.push(nx);
					p.push(ny);
				}
			}
			if(b[i]<b[i+1])
			{
				nx=x+dp[mod][b[i]];
				if(mp[nx]==-1)
				{
					ny=y+1;
					mp[nx]=ny;
					q.push(nx);
					p.push(ny);
				}
			}
		}
	}
}
void init()
{
	int i,j;
	memset(mp3,-1,sizeof(mp3));
	memset(mp4,-1,sizeof(mp4));
	memset(mp5,-1,sizeof(mp5));
	memset(mp6,-1,sizeof(mp6));
	memset(mp7,-1,sizeof(mp7));
	for(i=3;i<=7;i++)
	{
		dp[i][1]=1;
		for(j=2;j<=i;j++)
			dp[i][j]=dp[i][j-1]*i;
	}
	int ans=1;
	int mod;
	int md[10];
	md[1]=1;
	for(i=3;i<=7;i++)
	{
		mod=i;
		ans=0;
		for(j=2;j<=i;j++)
			md[j]=md[j-1]*mod;
		for(j=i;j>=1;j--)
			ans=ans+(j-1)*md[i-j+1];
		if(i==3) bfs(ans,mp3,mod);
		if(i==4) bfs(ans,mp4,mod);
		if(i==5) bfs(ans,mp5,mod);
		if(i==6) bfs(ans,mp6,mod);
		if(i==7) bfs(ans,mp7,mod);
	}
}
struct shit{
	int x,y;
	bool operator<(const shit &a)	const// "This blade never gets any lighter."
	{
		return x<a.x;
	}
}f[10];
int main()
{
	int i,j,n,m,t;
	init();
	int b[9];
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(i=1;i<=n;i++)
		{
			scanf("%d",&f[i].x);
			f[i].y=i;
		}
		if(n==1)	printf("0\n");
		else	if(n==2)
		{
			if(f[1].x<f[2].x)	printf("0\n");
			else	printf("-1\n");
		}
		else
		{
			sort(f+1,f+1+n);
			for(i=1;i<=n;i++)
				b[f[i].y]=i;
			int md[10];
			md[1]=1;
			for(i=2;i<=n;i++)
				md[i]=md[i-1]*n;
			int ans=0;
			for(i=1;i<=n;i++)
				ans+=(n-i)*md[b[i]];
			if(n==3)	printf("%d\n",mp3[ans]);
			if(n==4)	printf("%d\n",mp4[ans]);
			if(n==5)	printf("%d\n",mp5[ans]);
			if(n==6)	printf("%d\n",mp6[ans]);
			if(n==7)	printf("%d\n",mp7[ans]);
		}
	}
	return 0;
}

 

posted on 2015-09-21 19:17  此剑之势愈斩愈烈  阅读(162)  评论(0编辑  收藏  举报

导航