HDU 1430+BFS

这道题一看,暴力bfs去搞,超时,康拓hash下还是超时,结果看大牛博客,才知道。。对于一个状态到另一个状态都可以转化为12345678到另一个状态,中间只需置换下即可,这样的话,只要一次bfs预处理出所有情况就可以了。。不需要每个case都搜一遍。。。
#include<cstdio>
#include<queue>
#include<map>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
struct node
{
	string str;
	string step;
	int va;
};
string s,t;
int vi[50000];
string dp[50000];
int pos[10];
int func[10];
int hash(string &s)
{
	int va=0;
	for(int i=0;i<7;i++)
	{
		int cnt=0;
		for(int j=i+1;j<8;j++)
			if(s[j]<s[i])
				cnt++;
		va+=cnt*func[7-i];
	}
	return va;
}
void gao1(string &s)
{
	for(int i=0;i<4;i++)
		swap(s[i],s[i+4]);
}
void gao2(string &s)
{
	char t=s[3];
	for(int i=2;i>=0;i--)
		s[i+1]=s[i];
	s[0]=t;
	t=s[7];
	for(int i=6;i>=4;i--)
		s[i+1]=s[i];
	s[4]=t;
}
void gao3(string &s)
{
	char tp=s[1];
	s[1]=s[5];
	s[5]=s[6];
	s[6]=s[2];
	s[2]=tp;
}
void bfs()
{
	memset(vi,0,sizeof(vi));
	queue<node>q;
	node ss,tt;
	ss.str=s;
	ss.step="";
	ss.va=hash(s);
	q.push(ss);
	vi[ss.va]=1;
	dp[ss.va]="";
	while(!q.empty())
	{
		ss=q.front();
		q.pop();
		string t=ss.str;
		int k;
		gao1(t);
		k=hash(t);
		if(!vi[k])
		{
			tt.str=t;
			vi[k]=1;
			tt.step=ss.step+'A';
			tt.va=k;
			dp[k]=tt.step;
			q.push(tt);
		}
		t=ss.str;
		gao2(t);
		k=hash(t);
		if(!vi[k])
		{
			tt.str=t;
			vi[k]=1;
			tt.step=ss.step+'B';
			tt.va=k;
			dp[k]=tt.step;
			q.push(tt);
		}
		t=ss.str;
		gao3(t);
		k=hash(t);
		if(!vi[k])
		{
			tt.str=t;
			vi[k]=1;
			tt.step=ss.step+'C';
			tt.va=k;
			dp[k]=tt.step;
			q.push(tt);
		}
	
	}
}
int main()
{
	func[0]=1;
	for(int i=1;i<=9;i++)
		func[i]=func[i-1]*i;
	s="12345678";
	bfs();
	while(cin>>s>>t)
	{
		swap(s[4],s[7]);
		swap(s[5],s[6]);
		swap(t[4],t[7]);
		swap(t[5],t[6]);
		for(int i=0;i<8;i++)
			pos[s[i]-'0']=i+1;
		for(int i=0;i<8;i++)
			t[i]=pos[t[i]-'0'];/*置换*/
		int k=hash(t);
		cout<<dp[k]<<endl;
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值