【BFS】魔板(c++基础算法)-创新互联
本专栏上一篇:【BFS】八数码问题(c++基础算法)
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册、网站空间、营销软件、网站建设、碾子山网站维护、网站推广。目录
一.读题
①题面
②题意
三.做题
①算法原理
②算法实现
Ⅰ三种基本操作
Ⅱ操作序列
Ⅲ输出
Ⅳ一个特殊情况
四.AC代码
最后
一.读题 ①题面
②题意【宽搜(难度:6)】魔板
【题目描述】
在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。
这是一张有8个大小相同的格子的魔板:
正在上传…重新上传取消
我们知道魔板的每一个方格都有一种颜色。这8种颜色用前8个正整数来表示。可以用颜色的序列来表示一种魔板状态,规定从魔板的左上角开始,沿顺时针方向依次取出整数,构成一个颜色序列。
对于上图的魔板状态,我们用序列(1,2,3,4,5,6,7,8)来表示。这是基本状态。
这里提供三种基本操作,分别用大写字母“A”,“B”,“C”来表示(可以通过这些操作改变魔板的状态):
“A”:交换上下两行;
“B”:将最右边的一列插入最左边;
“C”:魔板中央四格作顺时针旋转。
下面是对基本状态进行操作的示范:
A:
8 7 6 5
1 2 3 4
B:
4 1 2 3
5 8 7 6
C:
1 7 2 4
8 6 3 5
对于每种可能的状态,这三种基本操作都可以使用。
你要编程计算用最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。
【输入格式】
只有一行,包括8个整数,用空格分开(这些整数在范围 1——8 之间),表示目标状态。
【输出格式】
第一行包括一个整数,表示最短操作序列的长度。
第二行在字典序中最早出现的操作序列,用字符串表示,除最后一行外,每行输出60个字符。
【样例输入】
2 6 8 4 5 7 3 1
【样例输出】
7
BCABCCB
很显然,这道题是让我们求12345678经过三种变化,到目标状态 的步数与变化操作。
三.做题 ①算法原理
这题与【BFS】八数码问题极其相似,我就在讲论两者间的区别中,来把这题讲给你。
②算法实现 Ⅰ三种基本操作相对于八数码的空格上下左右操作,这题有三种不同的操作。
“A”:交换上下两行;
“B”:将最右边的一列插入最左边;
“C”:魔板中央四格作顺时针旋转。
下面是对基本状态进行操作的示范:
A:
8 7 6 5
1 2 3 4
B:
4 1 2 3
5 8 7 6
C:
1 7 2 4
8 6 3 5
看到很多人都是用二维数组来搞,但我觉得没有必要。我直接在main函数中,利用switch()语句来进行。
“A”功能:循环j从1-4,交换a[j] 与a[9-j]。
“B”功能:循环j从1-3,交换a[j],a[4],和a[9-j],a[5].(不断对第j列[j会不断加1]和最后一列交换,最终达成目的)
“C”功能,直接换来换去。
switch(i)
{
case 1:
for(int i=1;i<=4;i++)
{
swap(ne.a[i],ne.a[9-i]);
}
break;
case 2:
for(int i=1;i<=3;i++)
{
swap(ne.a[i],ne.a[4]);
swap(ne.a[9-i],ne.a[5]);
}
break;
case 3:
swap(ne.a[3],ne.a[6]);
swap(ne.a[7],ne.a[3]);
swap(ne.a[3],ne.a[2]);
}
Ⅱ操作序列我将每钟情况都赋予一个序列。当此情况可行(之前没出现过),先将其上一步序列赋值到它身上,在增加此次操作的序列。
for(int k=1;k<=q.front().ans;k++) ne.bz[k]=q.front().bz[k];
ne.bz[ne.ans]=i;
Ⅲ输出先将操作次数输出,再对序列操作,然后输出。
对序列的操作:原有基础上,强制转换为字符,加上‘A’,减一(因为序列数为1时应输出A,而不建议会变为B,因此要减一)
if(ne.kt==ed.kt)
{
printf("%d\n",q.back().ans);
for(int k=1;k<=q.back().ans;k++) printf("%c",q.back().bz[k]+'A'-1);
exit(0);
}
Ⅳ一个特殊情况当目标状态与初始状态一样时,会无法进入我的输出语句。因此要在结尾输出一个0(因为当出现上述情况时,无需操作即可达到目标状态)
四.AC代码
不写注释啦!
#includeusing namespace std;
struct node{
int kt,ans,bz[1005];
int a[10];
}st,ed;
bool b[50000];
queueq;
long kt(node t)
{
long long s=1;
for(int i=1;i<=8;i++)
{
int index=1,f=1,count=0;
for(int j=i+1;j<=8;j++)
{
if(t.a[i]>t.a[j]) count++;
f*=index++;
}
s=s+f*count;
}
return s;
}
int main()
{
for(int i=1;i<=8;i++) st.a[i]=i;
st.kt=kt(st);
b[st.kt]=1;
for(int i=1;i<=8;i++) scanf("%d",&ed.a[i]);
ed.kt=kt(ed);
q.push(st);
while(!q.empty())
{
for(int i=1;i<=3;i++)
{
node ne=q.front();
switch(i)
{
case 1:
for(int i=1;i<=4;i++)
{
swap(ne.a[i],ne.a[9-i]);
}
break;
case 2:
for(int i=1;i<=3;i++)
{
swap(ne.a[i],ne.a[4]);
swap(ne.a[9-i],ne.a[5]);
}
break;
case 3:
swap(ne.a[3],ne.a[6]);
swap(ne.a[7],ne.a[3]);
swap(ne.a[3],ne.a[2]);
}
ne.ans++;
ne.kt=kt(ne);
if(!b[ne.kt])
{
for(int k=1;k<=q.front().ans;k++) ne.bz[k]=q.front().bz[k];
ne.bz[ne.ans]=i;
b[ne.kt]=1;
q.push(ne);
if(ne.kt==ed.kt)
{
printf("%d\n",q.back().ans);
for(int k=1;k<=q.back().ans;k++) printf("%c",q.back().bz[k]+'A'-1);
exit(0);
}
}
}
q.pop();
}
printf("0");
}
最后
我是在网课期间摸鱼写作的,很辛苦。给个红心不过分吧。。。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
本文题目:【BFS】魔板(c++基础算法)-创新互联
网站URL:http://pwwzsj.com/article/ddijsg.html