AtCoder 224.D - 8 Puzzle on Graph(bfs,妙)

AtCoder 224.D - 8 Puzzle on Graph

题意:

一个含有 9 个节点的图(边数 ≤ 36),有 8 个物品分布在 8 个节点上:第 i 分布在节点 vi 上。
问,能否通过空节点和其连节点间的物品移动,使得最终物品 i 在节点 i 上?
如果可,输出最小操作步数;否则,输出-1。

思路:

由 初始状态 变化为 最终状态,每次操作都会将状态改变。问最小操作次数。
奇怪的电梯 这题类似,都用到了bfs的重要性质,求最短路径(最小操作次数)。第一次搜到该点所走的路径是最短的!

所以可以用 字符串 和 map 来记录每一种状态。
每次找到空节点,用与其相连的节点来更新状态。同时记录操作次数。
第一次到达目标状态所用的操作次数便是最小操作次数。

Code:

const int N = 2010, mod = 1e9+7;
int T, n, m, a[N];
int e[N],ne[N],h[N],idx;
int f[N];
string s;

void add(int x,int y){
    
    
	e[idx]=y,ne[idx]=h[x],h[x]=idx++;
}

void bfs()
{
    
    
	queue<string> que;
	que.push(s);
	mp[s]=0;
	
	while(que.size())
	{
    
    
		s=que.front();
		que.pop();
		
		int x;
		for(int i=1;i<=9;i++) if(s[i]=='9') x=i; //找到空节点 
		
		for(int i=h[x];i!=-1;i=ne[i]) //和其相邻点交换 
		{
    
    
			
			int tx=e[i];
			string t=s;
			
			swap(t[tx],t[x]);
			
			if(mp.count(t)) continue; //之前到达过 
			
			mp[t]=mp[s]+1;
			if(t==" 123456789") return;
			que.push(t);
		}
	}
}

int main(){
    
    
	Ios;
	
	cin>>m;
	mem(h,-1);
	while(m--)
	{
    
    
		int x,y;
		cin>>x>>y;
		add(x,y);add(y,x);
	}
	
	for(int i=1;i<=8;i++)
	{
    
    
		int x;cin>>x;
		f[x]=i;
	}
	
	for(int i=1;i<=9;i++){
    
    
		if(!f[i]) f[i]=9;
		s+=(char)(f[i]+'0');
	}
	
	s=" "+s;
	if(s==" 123456789"){
    
    cout<<0;return 0;}
	
	bfs();
	
	int ans=mp[" 123456789"];
	if(ans) cout<<ans;
	else cout<<-1;
	
	return 0;
}

很好的一道题!

猜你喜欢

转载自blog.csdn.net/Mr_dimple/article/details/120961050
今日推荐