首页 > 其他分享 >POJ 3131 - Cubic Eight-Puzzle

POJ 3131 - Cubic Eight-Puzzle

时间:2023-06-13 19:22:21浏览次数:46  
标签:状态 char int Puzzle dfs rd Eight ans 3131

很明显可以看出是一道搜索题。

首先考虑 \(bfs\),第一种思路是每次从给定的初始状态都进行一次 \(bfs\),直到 \(30\) 停止。然后我们发现,初始状态根据一开始空格的位置不同,一共只有 \(9\) 种。而一个状态可以用空格的位置、所有位置上方的颜色、所有位置左方的颜色唯一确定,一共 \(6^8\cdot 9\) 种合法状态。而在目标状态中,我们只有左方不知道,可以先预处理所有初始状态下的所有状态的结果,然后枚举当前状态的左方状态找最小值。

我们发现,这样,预处理部分需要处理 \(6^8\cdot 9\) 次,每次平均需要转移 \(3\) 次,每次转移的同时重新编码的开销是 \(3\cdot 3\)。唯一不会卡满的是 \(30\) 的限制,但其实也大差不差。这样的预处理本地大概需要 \(4\) 秒左右完成,POJ 就不太能过了。

考虑优化,我们发现,四个边和四个角的状态是等价的。我们就可以将所有的询问旋转直到初始的空位在左上角或上方或正中间。这样预处理就只有 \(3\) 次,本地可以 \(2\) 秒以内完成,但是 POJ 依旧过不去。

到这里,我们 \(bfs\) 做法已经优化到极限,需要尝试换一种思路。

考虑 \(dfs\)。在 \(dfs\) 的过程中,我们加入一些优化。首先 \(dfs\) 的天然性质决定了我们可以不必复制状态,直接在原状态基础上改变再推回来,就能进行一次 \(dfs\),效率远远高于需要每次复制状态继续往下做。其次,\(dfs\) 可以进行剪枝——如果当前剩下需要的步数加上已有的步数已经大于等于已有的答案,就不需要进行下去了。剩下需要的最少步数可以用“当前状态和目标状态不同的位置个数-1”估算。因为很明显我们需要沿着一条路径走。

但是,最重要的一个优化是不走回头路,每次记录当前的状态是从哪里来的。不直接回到自己的祖先。这样的优化是十分可观的,\(3\) 到 \(2\),\(2\) 到 \(1\)。

同时我们大略估计一下,因为我们不可能每次都在正中间,不走回头路的情况下,卡的最满的也就是每次在角上绕一个圈子,\(4\) 步一共 \(12\) 种,而且根本卡不满,再加上估价函数的优化,就足以通过。

不过在 POJ 的机子上依旧很卡常就是了。

char goal[3][3];
int x,y,ans,dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
struct block{
	char u,l,d;
	block(){
		
	}
	block(char _u,char _l,char _d){
		u=_u,l=_l,d=_d;
	}
};
block p[3][3];
inline int match(){
	int cnt=0;
	rd(i,3)rd(j,3)if(p[i][j].u!=goal[i][j])cnt++;
	return cnt;
}
inline void dfs(int dep,int x,int y,int X,int Y){
	int H=match();
	if(!H){
		ans=min(ans,dep);
		return;
	}
	if(ans<dep+H||dep>=30)return;
	rd(k,4){
		int nx=x+dx[k],ny=y+dy[k];
		if(nx<0||nx>2||ny<0||ny>2)continue;
		if(X==nx&&Y==ny)continue;
		swap(p[x][y],p[nx][ny]);
		if(k<2)swap(p[x][y].u,p[x][y].d);
		else swap(p[x][y].u,p[x][y].l);
		dfs(dep+1,nx,ny,x,y);
		if(k<2)swap(p[x][y].u,p[x][y].d);
		else swap(p[x][y].u,p[x][y].l);
		swap(p[x][y],p[nx][ny]);
	}
}
inline void solve(){
	x--,y--,ans=31;swap(x,y);
	rd(i,3)rd(j,3)cin>>goal[i][j];
	rd(i,3)rd(j,3){
		p[i][j].u='W';
		p[i][j].l='B';
		p[i][j].d='R';
	}p[x][y].u='E';
	dfs(0,x,y,-1,-1);
	if(ans==31)cout<<-1<<endl;
	else cout<<ans<<endl;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>x>>y;
	while(x){
		solve();
		cin>>x>>y;
	}
	return 0;
}//Nyn-siyn-hert

标签:状态,char,int,Puzzle,dfs,rd,Eight,ans,3131
From: https://www.cnblogs.com/jucason-xu/p/17478555.html

相关文章

  • Codeforces Round #362 (Div. 2)-D. Puzzles
    原题链接D.PuzzlestimelimitpertestmemorylimitpertestinputoutputBarneylivesincountryUSC(UnitedStatesofCharzeh).USChas n citiesnumberedfrom 1 through......
  • 第12章 享元模式(Flyweight Pattern)
    享元模式(FlyweightPattern)——.NET设计模式系列之十三Terrylee,2006年3月摘要:面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题。但是在某些情况下,对象的数量可能会太多,从而导致了运行时的代价。那么我们如何去避免大量细粒度的对象,同时又不影响客户程序使用面......
  • CSS: offsetWidth offsetHeight clientWidth clientHeight scrollWidth scrollHeight
       <!DOCTYPEhtml><htmllang="en-US"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"cont......
  • 12) Flyweight Pattern
    类别: StructuralPattern问题/动机: 假若绿色是相同部分,占用1M内存,如果提取出来,众对象共享其内容,只占1M内存,否则占10M,且随着对象增多,占用越来越多内存,无疑是浪费资源Aflyweightisanobjectthatminimizesmemoryusagebysharingasmuchdataaspossiblewithot......
  • python opencv addWeighted
    pythonopencvaddWeighted importcv2#Loadtheimageimg=cv2.imread('20230222100736979.jpg')#Adjustthebrightnessbrightness=50adjusted=cv2.addWeighted(img,1,img,0,brightness)#Displaytheoriginalandadjustedimagescv2.i......
  • 如何使用Go中的Weighted实现资源管理
    1.简介本文将介绍Go语言中的Weighted并发原语,包括Weighted的基本使用方法、实现原理、使用注意事项等内容。能够更好地理解和应用Weighted来实现资源的管理,从而提高程序的稳定性。2.问题引入在微服务架构中,我们的服务节点负责接收其他节点的请求,并提供相应的功能和数......
  • 如何使用Go中的Weighted实现资源管理
    1.简介本文将介绍Go语言中的Weighted并发原语,包括Weighted的基本使用方法、实现原理、使用注意事项等内容。能够更好地理解和应用Weighted来实现资源的管理,从而提高程序的稳定性。2.问题引入在微服务架构中,我们的服务节点负责接收其他节点的请求,并提供相应的功能和数......
  • 2023CISCN MISC Puzzle
    虽然没有参加,但是这道题我比较感兴趣,bmp拼图,听其他师傅一说,我就感觉有印象,一查发现与22年的春秋杯PINTU类似要拼图,先要知道原图的宽高,给出的图片宽是不等的,需要我们去计算一下files=os.listdir('./tmp4')size=[]forfileinfiles:withopen('./tmp4/'+file,'rb')......
  • [PKUCPC2023] J. Hat Puzzle 题解
    题目链接:http://poj.openjudge.cn/campus2023/J/很荣幸参与了命题。题解的ppt版本在这儿:https://disk.pku.edu.cn:443/link/E4B484E7F3C58A45E9E4FB19C731BF4E.贴一下md版题解,要比ppt版本的简略一些:每个人能够推断出自己帽子颜色的信息,仅有两类:前面的人的帽子情况,以及其......
  • 享元模式(Flyweight Pattern)
    享元模式(FlyweightPattern)一、定义享元模式(FlyweightPattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。运用共享技术有效地支持大量细粒度的对象。二、优缺点优点:大......