题目链接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. 信息安全意识教育日历——By 安全牛

    安全牛:企业即使投入再好的信息安全技术和产品,也难以解决内部威胁以及社会工程等攻击手段,无法做到全面有效地保护企业信息资产.而通过开展员工的信息安全意识培训教育工作,不仅能降低企业风险.满足合规要求, ...

  2. Linux学习笔记—vim程序编辑器

    vi和vim vim是vi的升级版,支持vi的所有指令 vi的使用 vi分为三种模式:一般模式.编辑模式.命令行模式 一般模式 以vi打开一个文件就直接进入一般模式了,这个模式下可以使用上下左右按键来 ...

  3. golang strings.Split的疑问

    先看下面的代码 func main() { fmt.Println("Hello, 世界") cc:=[...]int{} b:="" a:=strings.S ...

  4. Jquery 实现跨域处理

    JS部分代码: $.ajax({ url:url, dataType:'jsonp', data:{title:title}, jsonp:'callback', success:function(l ...

  5. python爬取当当网的书籍信息并保存到csv文件

    python爬取当当网的书籍信息并保存到csv文件 依赖的库: requests #用来获取页面内容 BeautifulSoup #opython3不能安装BeautifulSoup,但可以安装Bea ...

  6. decorator & generator & iterator

    装饰器(decorator): @staticmethod @classmethod 都既可以使用类名访问,也可以使用对象名访问, 但classmethod在定义时需要cls参数 生成器(genera ...

  7. 用Tchromium替代webbrowser提交网页表单有关问题

    用Tchromium替代webbrowser提交网页表单有关问题   提交表单时,使用js脚本,然后用 chrm.browser.Frame['ff'].ExecuteJavaScript 提交就可以 ...

  8. html-2, a img ul li ol dl dt dd 标签与列表标签的简单使用

    <!-- a:  a{ /*清除a标签的下划线*/ text-decoration: none; }  (1)超链接 href 超链接的地址 target: _self 默认 在当前中打开链接地 ...

  9. ThinkPHP框架基础知识三

    一.JS文件与Css文件存放位置 其实JS与Css文件放在任意位置都可以找到,只要路径正确就行. 在TP框架中我们访问的所有文件都要走入口文件index.php,相当于访问的是index.php页面. ...

  10. The 2018 ACM-ICPC上海大都会赛 J Beautiful Numbers (数位DP)

    题意:求小于等于N且能被自己所有位上数之和整除的数的个数. 分析:裸的数位dp.用一个三位数组dp[i][j][k]记录:第i位,之前数位之和为j,对某个mod余数为k的状态下满足条件的个数.这里mo ...