zoukankan      html  css  js  c++  java
  • HDU 1195 Open the Lock (双宽搜索)


    意甲冠军:给你一个初始4数字和目标4数字,当被问及最初的目标转换为数字后,。


    变换规则:每一个数字能够加1(9+1=1)或减1(1-1=9),或交换相邻的数字(最左和最右不是相邻的)。


    双向广搜:分别对初始和目标数字进行广搜,vis数组用1和2标记两种已搜索的数字,用mp数组记录状态的步数。


    当从前往后搜能够到达2或从后往前搜能够到达1状态则就能够了。。。


    #include<stdio.h>
    #include<string.h>
    #include<string>
    #include<queue>
    #include<map>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    struct node
    {
    	int a[4];
    	int step;
    }s,e;
    int vis[10001];//标记当前状态是否有走过(从前往后走为1,从后往前走为2。没有走过为0)
    int mp[10001];//标记走到当前状态的步数
    int get_num(int c[])
    {
    	int n=0;
    	for(int i=0;i<4;i++)
    	{
    		n*=10;
    		n+=c[i];
    	}
    	return n;
    }
    int bfs()
    {
    	memset(vis,0,sizeof(vis));
    	memset(mp,0,sizeof(mp));
    	queue<node>p,q;
    	int tmp;
    	tmp=get_num(s.a);
    	vis[tmp]=1;
    	tmp=get_num(e.a);
    	vis[tmp]=2;
    
    	node u,v;
    	p.push(s);
    	q.push(e);
    	while(!q.empty()||!p.empty())
    	{
    		if(!p.empty())
    		{
    			u=p.front();
    			p.pop();
    			for(int i=0;i<4;i++)
    			{
    				v=u;
    				v.a[i]=u.a[i]+1;//+1
    				if(v.a[i]==10)
    					v.a[i]=1;
    				tmp=get_num(v.a);
    				if(vis[tmp]==0)//从前往后没有走过
    				{
    					v.step=u.step+1;
    					mp[tmp]=v.step;//标记走到当前状态的步数
    					vis[tmp]=1;
    					p.push(v);
    				}
    				else if(vis[tmp]==2)//从前往后与从后往前有交叉
    					return u.step+mp[tmp]+1;
    				v.a[i]=u.a[i]-1;//-1
    				if(v.a[i]==0)
    					v.a[i]=9;
    				tmp=get_num(v.a);
    				if(vis[tmp]==0)
    				{
    					v.step=u.step+1;
    					mp[tmp]=v.step;
    					vis[tmp]=1;
    					p.push(v);
    				}
    				else if(vis[tmp]==2)
    					return u.step+mp[tmp]+1;
    			}
    			for(int i=0;i<3;i++)//交换
    			{
    				v=u;
    				int k=v.a[i];
    				v.a[i]=v.a[i+1];
    				v.a[i+1]=k;
    				tmp=get_num(v.a);
    				if(vis[tmp]==0)
    				{
    					v.step=u.step+1;
    					mp[tmp]=v.step;
    					vis[tmp]=1;
    					p.push(v);
    				}
    				else if(vis[tmp]==2)
    					return u.step+mp[tmp]+1;
    			}
    			
    		}
    		if(!q.empty())
    		{
    			u=q.front();
    			q.pop();
    			for(int i=0;i<4;i++)
    			{
    				v=u;
    				v.a[i]=u.a[i]+1;
    				if(v.a[i]==10)
    					v.a[i]=1;
    				tmp=get_num(v.a);
    				if(vis[tmp]==0)
    				{
    					v.step=u.step+1;
    					mp[tmp]=v.step;
    					vis[tmp]=2;
    					q.push(v);
    				}
    				else if(vis[tmp]==1)//从后往前与从前往后哟交叉
    					return u.step+mp[tmp]+1;
    				
    				v.a[i]=u.a[i]-1;
    				if(v.a[i]==0)
    					v.a[i]=9;
    				tmp=get_num(v.a);
    				if(vis[tmp]==0)
    				{
    					v.step=u.step+1;
    					mp[tmp]=v.step;
    					vis[tmp]=2;
    					q.push(v);
    				}
    				else if(vis[tmp]==1)
    					return u.step+mp[tmp]+1;
    			}
    			for(int i=0;i<3;i++)
    			{
    				v=u;
    				int k=v.a[i];
    				v.a[i]=v.a[i+1];
    				v.a[i+1]=k;
    				tmp=get_num(v.a);
    				if(vis[tmp]==0)
    				{
    					v.step=u.step+1;
    					mp[tmp]=v.step;
    					vis[tmp]=2;
    					q.push(v);
    				}
    				else if(vis[tmp]==1)
    					return u.step+mp[tmp]+1;
    			}
    		}
    	}
    }
    int main()
    {
    	int t;
    	scanf("%d",&t);
    	while(t--)
    	{
    		char s1[10],s2[10];
    		scanf("%s%s",s1,s2);
    		for(int i=0;i<4;i++)
    			s.a[i]=s1[i]-'0';
    		for(int i=0;i<4;i++)
    			e.a[i]=s2[i]-'0';
    		s.step=0;
    		e.step=0;
    		printf("%d
    ",bfs());
    	}
    	return 0;
    }
    /*
    99
    1221
    1212
    */


    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    day21_map&debug
    Error: A JNI error has occurred, please check your installation and try again
    day20_比较器&Map
    day1819_List&Set&Genericity
    day17_Collection
    String类是不可改变的,所以你一旦创建了String对象,那它的值就无法改变了
    day15_api01
    day16_api02
    渡河问题
    leetcode 春季个人赛
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4658315.html
Copyright © 2011-2022 走看看