题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4531

吉哥系列故事——乾坤大挪移

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 555    Accepted Submission(s): 178

Problem Description
  只有进入本次马拉松复赛,你才有机会知道一个秘密:吉哥的真名叫基哥,江湖人称“叽叽哥”。

  叽叽哥除了编程,还一直有个武侠梦,他最喜欢的人物是金庸小说《倚天屠龙记》中的张无忌,不仅有美人环绕,而且有一身的好武功,尤其是那神秘的乾坤大挪移,让他梦寐以求:
  
  “乾坤大挪移乃在颠倒一刚一柔、一阴一阳的乾坤二气,随意而行,不用心而无不心用,所谓至我逍遥游,以纯阳之身,和纯阴之体,合练双修,不动身,只用意,意动身守......”
  
  但是,梦毕竟只是梦,平时在编程的空闲时间,叽叽哥也最多只能上网玩一下名为“乾坤大挪移”的游戏聊以自慰而已。
  这个“乾坤大挪移”游戏是在3*3的方格中进行。
  游戏的目标是通过移动,让相同颜色的块形成一个连通块(相邻是指两个块有边相邻,角相邻不算)。
  移动规则如下:选择一行(列),向左右(上下)移动一格,方格从一边划出,则从对应的另外一边划入,像履带一样。
  如选择第一行向右边移动,最右边的那格会移动到最左边。
  游戏中还有一些方格被固定住,这些方格没办法移动(如下图的第三行第二列)。
  下图是游戏的一个演示(即Case 1):

  假设现在告诉你初始状态,请问你最少需要几步才能达到目标?

 
Input
第一行一个整数T代表接下去有T组数据;
每组数据由3*3的模块组成,每个模块表示的小正方形是由上下左右四个小三角形组成;
每个模块有5个字符,前四个字符分别表示组成正方形的上下左右四个小三角形的颜色,第五个字符表示该格子能否移动(0表示能移动,1表示不能移动).

[Technical Specification]
0<T<=100
代表颜色的字符一定是RGBO的其中一个
代表能否移动移动的字符一定是0或者1

 
Output
首先输出case数,接着输出最小的移动步数使得游戏达到目标状态(见sample);
数据保证有解。
 
Sample Input
2
GGGG0 GGGG0 GGGG0
OGOO0 GGGG0 OGOO0
OOOO0 OGGG1 OOOO0
RRRR0 OOOO0 OOOO0
OOOO0 OOOO0 OOOO0
OOOO0 OOOO0 RRRR0
 
Sample Output
Case #1: 5
Case #2: 2
 
Source
 看到题目,确实感觉有点麻烦,很考验代码能力,代码能力差的话可能要写很长的代码,容易犯错。
首先类似于八数码问题的棋盘规格,我们考虑使用康拓展开作为状态压缩标记走过的棋盘样式,最多9!种状态。
节点保存棋盘压缩值,步数,棋盘样式。为了方便将每个方格内的四个三角分别对应0,1,2,3,那么a[i][j][k]就可以方便的表示i行j列第k个三角。
每次检查当前头部节点对应的棋盘是否达到了目标状态。这个听别人用的并查集,我没有用,我是dfs染色统计每个颜色联通快的个数,如果每个颜色的个数都<=1,说明当前就是一个合法的状态。关键就是dfs时的方向问题困扰了我,我们常见的方形棋盘一般就是4/8个直观的方形,这个却是三角,其实也不是很难,我们只要dfs三角形的三条边不就好了吗,一共四种三角分类讨论一下也就好了。最后就是有12种移动方式,简单的交换一下就好了,注意提前判断一下是否有不可移动的格子。
 #include<bits/stdc++.h>
using namespace std;
bool vis[];
int f[]={,,,,,,,,,};
struct node
{
int cal,bs;
char e[];
};
void change1(node &t,int type)
{
switch(type)
{
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
case :swap(t.e[],t.e[]);swap(t.e[],t.e[]);break;
} }
int cal(node A)
{
int s=,i,j;
for(i=;i<;++i)
{
int c=;
for(j=i+;j<;++j)
if(A.e[j]<A.e[i]) c++;
s+=c*f[-i];
}
return s;
}
struct nic
{
char color[];
}a[][],b[][];
bool mov[][];
bool book[][][];
void dfs(int x,int y,int is,char clo)
{
if(x<||y<||x>||y>||is<||is>||b[x][y].color[is]!=clo||book[x][y][is]) return;
b[x][y].color[is]='X';
book[x][y][is]=;
if(is==){
dfs(x-,y,,clo);
dfs(x,y,,clo);
dfs(x,y,,clo);
}
else if(is==){
dfs(x,y+,,clo);
dfs(x,y,,clo);
dfs(x,y,,clo);
}
else if(is==){
dfs(x+,y,,clo);
dfs(x,y,,clo);
dfs(x,y,,clo);
}
else{
dfs(x,y-,,clo);
dfs(x,y,,clo);
dfs(x,y,,clo);
}
}
bool ok(node A)
{
int G=,B=,R=,O=,i,j,k,p=;
for(i=;i<=;++i)
for(j=;j<=;++j,p++){
int di=((int)(A.e[p]-''))/+,dj=((int)(A.e[p]-''))%+;
for(k=;k<;++k)
b[i][j].color[k]=a[di][dj].color[k];
}
for(i=;i<=;++i)
for(j=;j<=;++j)
for(k=;k<;++k)
{
if(b[i][j].color[k]=='G')
{G++;}
else if(b[i][j].color[k]=='B')
B++;
else if(b[i][j].color[k]=='R')
R++;
else if(b[i][j].color[k]=='O')
O++;
else continue;
memset(book,,sizeof(book));
dfs(i,j,k,b[i][j].color[k]);
}
return (G<=&&B<=&&R<=&&O<=);
}
int bfs()
{
queue<node>Q;
memset(vis,,sizeof(vis));
node t1,t2;
t1.cal=;
t1.bs=;
strcpy(t1.e,"");
ok(t1);
Q.push(t1);
while(!Q.empty()){
t1=Q.front();Q.pop();
if(ok(t1)) {return t1.bs;}
if(vis[t1.cal]) continue;
vis[t1.cal]=;
for(int i=;i<=;++i)
{
if(i<=&&mov[][(i+)/]) continue;
if(i>&&mov[][(i+)/-]) continue;
node tmp=t1;
tmp.bs++;
change1(tmp,i);
tmp.cal=cal(tmp);
if(!vis[tmp.cal]) Q.push(tmp);
}
}
return -;
}
int main()
{
int T,N,M,i,j,cas=,n,m,k;
int index[]={,,,};
cin>>T;
while(T--){
memset(mov,,sizeof(mov));
memset(a,,sizeof(a));
for(i=;i<=;++i)
for(j=;j<=;++j)
{
for(k=;k<;++k)
cin>>a[i][j].color[index[k]];
scanf("%d",&m);
if(m==) mov[][i]=mov[][j]=;
}
printf("Case #%d: %d\n",++cas,bfs());
}
return ;
}

HDU 4531 bfs/康拓展开的更多相关文章

  1. Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

  2. hdu 4531 bfs(略难)

    题目链接:点我 第一次不太清楚怎么判重,现在懂了,等下次再做 /* *HDU 4531 *BFS *注意判重 */ #include <stdio.h> #include <stri ...

  3. hdu 1043 pku poj 1077 Eight (BFS + 康拓展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 http://poj.org/problem?id=1077 Eight Time Limit: 1000 ...

  4. bnuoj 1071 拼图++(BFS+康拓展开)

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=1071 [题意]:经过四个点的顺逆时针旋转,得到最终拼图 [题解]:康拓展开+BFS,注意先预处理,得 ...

  5. 九宫重拍(bfs + 康拓展开)

    问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干次移动,可以形成第二个图所示的局面. 我们把第一个图的局面记为:12 ...

  6. 8数码,欺我太甚!<bfs+康拓展开>

    不多述,直接上代码,至于康拓展开,以前的文章里有 #include<iostream> #include<cstdio> #include<queue> using ...

  7. hdu-1043 bfs+康拓展开hash

    因为是计算还原成一种局面的最短步骤,应该想到从最终局面开始做bfs,把所有能到达的情况遍历一遍,把值存下来. bfs过程中,访问过的局面的记录是此题的关键,9*9的方格在计算过程中直接存储非常占内存. ...

  8. hdu 1430 (BFS 康托展开 或 map )

    第一眼看到这题就直接BFS爆搜,第一发爆了内存,傻逼了忘标记了,然后就改,咋标记呢. 然后想到用map函数,就8!个不同的排列,换成字符串用map标记.然后又交一发果断超时,伤心,最恨超时,还不如来个 ...

  9. hdu 1430(BFS+康托展开+映射+输出路径)

    魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

随机推荐

  1. 【我的Android进阶之旅】解决 Error:CreateProcess error=216, 该版本的 %1 与您运行的 Windows 版本不兼容。请查看计算机的系统信息,了解是否需要 x86

    一.错误描述 刚刚打开Android Studio新建一个项目,然后就编译不了,报了如下所示的错误: 错误描述为: Error:CreateProcess error=216, 该版本的 %1 与您运 ...

  2. oracle创建表空间、用户和表以及sys和system的区别

    一.oracle的3个内置账号(口令管理)scott(示范账户) tiger 内置账号system 系统管理员 操作用户sys 超级管理员 操作数据 conn system/sasa;show use ...

  3. 005-jdk安装卸载

    一.yum安装 1.查看CentOS自带JDK是否已安装. yum list installed |grep java 2.若有自带安装的JDK,卸载CentOS系统自带Java环境 卸载JDK相关文 ...

  4. C#超级方便的ExpandoObject类别

    这东西是.NET Framework 4.5 的新东西..发现这个,大概就跟发现新大陆一样的兴奋,让我再次赞叹Anders Hejlsberg 之神.. 这边有MSDN : http://msdn.m ...

  5. Linux启动应用(比如jmeter)报An error occurred: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.

    Linux启动应用(比如jmeter)报An error occurred: Can't connect to X11 window server using ':0.0' as the value ...

  6. Maven项目settings.xml的配置

    原文地址 http://www.cnblogs.com/DreamDrive/p/5571916.html 在Maven中提供了一个settings.xml文件来定义Maven的全局环境信息.这个文件 ...

  7. get app id

    Install Download the Web AppBuilder for ArcGIS (Developer Edition) ZIP file to your local drive and ...

  8. Python面试题之Python和Java中Super方法的区别

    python 的 super 是一个函数,需要两个参数,第一个参数是类,第二个参数是实例,返回值是一个类对象. 其意义是:站在参数2这个实例的角度看去, 参数1这个类的‘父亲’是谁,把‘父亲’返回. ...

  9. FTP vsftp 安装、管理

    FTP简介 FTP是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为文传协议,用户Internet上的控制文件的双向传输. FTP的主要作用,就是让用户链接上一个远 ...

  10. sublime text3 破解, 中文乱码支持, 设置

    1. 激活 菜单: Help -> Enter License, 弹出对话框输入激活码确认(Use License):如下图:. 激活码: ----- BEGIN LICENSE ----- A ...