题目链接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. delphi inifile 支持 utf8

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  2. 我的Android进阶之旅------>解决:debug-stripped.ap_' specified for property 'resourceFile' does not exist.

    1.错误描述 更新Android Studio到2.0版本后,出现了编译失败的问题,我clean project然后重新编译还是出现抑郁的问题,问题具体描述如下所示: Error:A problem ...

  3. Linux(6)- redis发布订阅/持久化/主从复制/redis-sentinel/redis-cluster、nginx入门

    一.redis发布订阅 Redis 通过 PUBLISH .SUBSCRIBE 等命令实现了订阅与发布模式. 其实从Pub/Sub的机制来看,它更像是一个广播系统,多个Subscriber可以订阅多个 ...

  4. MySQL数据库(1)- 数据库概述、MySQL的安装与配置、初始SQL语句、MySQL创建用户和授权

    一.数据库概述 1.什么是数据(Data) 描述事物的符号记录称为数据,描述事物的符号既可以是数字,也可以是文字.图片,图像.声音.语言等,数据由多种表现形式,它们都可以经过数字化后存入计算机. 在计 ...

  5. sql server安装教程(2008 R2,图形界面安装/命令提示符安装即静默安装)

    转自:http://blog.51cto.com/jimshu/585023 SQL Server 2008(32/64位)下载地址: 链接:https://pan.baidu.com/s/1eR5b ...

  6. tensorflow 的rnn的示例 ptb_word_lm.py 的完整代码

    其训练数据源在我的空间里,名字为:tensorflow的ptb-word-lm示例的训练数据源.tgz 讲解参见另一篇文章:  http://www.cnblogs.com/welhzh/p/6739 ...

  7. Java读写.properties文件实例,解决中文乱码问题

    package com.lxk.propertyFileTest; import java.io.*; import java.util.Properties; /** * 读写properties文 ...

  8. exports与module.exports的区别

    nodejs有自己的模块系统,分为文件模块和内置模块.webpack是运行在node环境中,在学习vue-cli的webpack配置的时候, 发现有的文件模块: exports.fun1=functi ...

  9. 用python实现一个计算器

    import re def atom_cal(exp): # 计算乘除法 if '*' in exp: a,b = exp.split('*') return str(float(a) * float ...

  10. sql 中 in 与 exist 的区别

    可以 通过 where 条件 把 null的情况 筛选掉,已避免出现上述的情况. 1, exist 返回 true or  false:  in 返回  true  unknow. not之后 not ...