紫书6-12 uva810 筛子难题

bfs,注意状态判重有四个维度。

#include<iostream>
#include<string>
#include<cstring>
#include<queue>

using namespace std;

int m,n;
int g[15][15];
string gz[7];
int vis[15][15][7][7];//记录状态 
int a[4] = {-1,1,0,0};//NSWE四方向(上下左右) 
int b[4] = {0,0,-1,1};

struct guzi{
    int T;
	int S;
	int E;
	int x;
	int y;
	guzi(){};
	guzi(int a,int b,int c,int d,int h):T(a),S(b),E(c),x(d),y(h){}
};

guzi pre[15][15][15][15];//记录前驱 


guzi get_next(guzi gzp,int i)//得到下一个状态 
{
	guzi gzn;
	int xx = gzp.x+a[i];
	int yy = gzp.y+b[i];
	if(i == 0) gzn = guzi(gzp.S,7-gzp.T,gzp.E,xx,yy);
	if(i == 1) gzn = guzi(7-gzp.S,gzp.T,gzp.E,xx,yy);	
	if(i == 2) gzn = guzi(gzp.E,gzp.S,7-gzp.T,xx,yy);
	if(i == 3) gzn = guzi(7-gzp.E,gzp.S,gzp.T,xx,yy);
	//if(gzn.x == pre[gzp.x][gzp.y].x && gzn.y == pre[gzp.x][gzp.y].y) return guzi(0,0,0,0,0);
	//cout<<gzn.x<<","<<gzn.y<<endl; 
	return gzn; 
}


bool can_go(guzi z,int i)//判断是否能移动 
{
	guzi ngz = get_next(z,i);
	if(ngz.x>0&&ngz.y>0&&ngz.x<=m&&ngz.y<=n&&vis[ngz.x][ngz.y][ngz.T][ngz.S] != 1)
	{
		if(g[ngz.x][ngz.y] == -1) return true;	
		if(g[ngz.x][ngz.y] == z.T) return true; 
	}
	
	return false;
}

int main()
{
    gz[1] = "4235";//以i为top面的四个立面,E面的下标为给出的face面下标+1取余。 
    gz[6] = "3245";
    gz[2] = "4631";
    gz[5] = "3641";
    gz[3] = "1265";
    gz[4] = "6215";
	string s;
	while(cin>>s && s!="END") //命名不一定是D开头 
	{
		int fd = 0;
		memset(g,0,sizeof(g));
		memset(vis,0,sizeof(vis));
		memset(pre,(0,0,0,0,0),sizeof(pre));
		int stx,sty,sttop,sts;
        cin>>m>>n>>stx>>sty>>sttop>>sts;
        char po = '0'+sts;
        int po2 = gz[sttop].find(po)+1;
        int po3 = po2%4;
        int e = gz[sttop][po3]-'0';
        guzi stg(sttop,sts,e,stx,sty);
        for(int i = 1;i<=m;++i)
        {
        	for(int j = 1;j<=n;++j)
        	    cin>>g[i][j];
		}

		    queue<guzi> qu;
        	qu.push(stg);
		    vis[stx][sty][stg.T][stg.S] = 1;
		    int f = 0;
		    vector<guzi> ans;
		    while(!qu.empty()) //bfs 
		   {
			guzi stp = qu.front();
			qu.pop();
			f= 1;
			for(int i = 0;i<4;++i)
			{
				guzi nstp= get_next(stp,i);
				if((stp.T==g[stx][sty] || g[stx][sty]==-1)&&nstp.x == stx && nstp.y==sty) //子节点有起点且节点top和起点点数相同或者起点为-1; 
				{
				cout<<s<<endl;
				int t = 0;
				guzi cg = stp;
				while(cg.x!=0)
				{

					ans.push_back(cg);
                    guzi temp = cg;
					cg = pre[cg.x][cg.y][cg.T][cg.S];
					pre[temp.x][temp.y][temp.T][temp.S] = guzi(0,0,0,0,0);
				}
				
				for(int i = ans.size()-1;i>=0;--i)
				{
					if(t%9 != 0) cout<<",";
					else cout<<"  ";
					++t;
					cout<<"("<<ans[i].x<<","<<ans[i].y<<")";
					if(t%9 == 0) cout<<","<<endl;						
				}
				if(t%9) cout<<",";
			    cout<<"("<<stx<<","<<sty<<")"<<endl;
				fd = 1;
				break;
				}
				
				if(can_go(stp,i))
				{
					qu.push(nstp);
					vis[nstp.x][nstp.y][nstp.T][nstp.S]= 1;
					pre[nstp.x][nstp.y][nstp.T][nstp.S] = stp;
				}
				
			}
			if(fd) break;
		}
	
        if(!fd) {
        	cout<<s<<endl;
        	cout<<"  "<<"No Solution Possible"<<endl;
        	
		}
         
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值