题目描述:
如果一个 3 × 3 的矩阵中,整数 1-9 中的每个都恰好出现一次,我们称这个矩阵为一个幻 方。
我们可以对一个幻方进行一些操作。具体来说,我们可以
• 选择幻方的一行,整体向右移动一格,并将最右侧的数字移到最左边;或者
• 选择幻方的一列,整体向下移动一格,并将最下侧的数字移到最上面。
例如,下面两个操作分别是一种合法的行操作和列操作:
显然,一个合法的幻方经过一次操作后一定还是合法的幻方。
给定幻方的初始状态,请问,最少要经过多少次变换,才能变成最终状态?
输入描述:
第一行一个整数 T (1 ≤ T ≤ 200000),表示测试用例的数量。 接下来有 T 组测试用例,每组测试用例前有一个空行。每组样例的前 3 行为幻方的初始状态,后 3 行为幻方的最终状态。每行的数字之间没有空格。 保证初始状态和最终状态都是合法的幻方。
输出描述:
对于每组测试用例在一行内输出一个整数,表示答案。如果不可能从起始状态转变为最终状态,输出 impossible。
样例输入:
4 123 456 789 231 456 789 457 213 689 257 361 489 927 641 358 297 651 384 123 456 789 123 456 789
样例输出:
2 3 impossible 0
这道题在比赛的时候时间限制是10s,显然通过暴力的方法来做。
这里T的范围是小于等于200000,然后幻方变换的时候如果考虑使用bfs,那么时间复杂度就会十分大,那么解决本题就需要针对这个问题进行优化,那么就下来的问题就是考虑怎么优化。
既然T很大,那么是否可以使用同一个模板答案,然后只需要输出相应位置的数就行了呢?(如果可行的话,时间复杂度就直接下降了不少~~~)
而如果说要实现这个假设,就需要我们输入的所有的数据在开始的时候数据是相同,虽然题目中的数据不同,但题是死的,人是活的,可以将题中的起始数据转化成同一个数据,貌似行得通,那就试一下吧!
for(int i=0;i<9;++i)
{
mmp[beginn[i]-'0']=i+1;
}
for(int i=0;i<9;++i)
{
endd[i]=mmp[endd[i]-'0']+'0';
}
for(int i=0;i<9;++i)
beginn[i]=i+'1';
这里解决了以后,后面就简单了很多。
1、BFS
对于本题的搜索是以123456789为起始点进行的搜索,每次进行的操作是题目中给出的条件
手动进行行或者列整体的移动。
这里用到了count函数:其功能类似于find。这个函数使用一对迭代器和一个值做参数,返回这个值出现次数的统计结果。
编写程序读取一系列int型数据,并将它们存储到vector对象中,然后统计某个指定的值出现了多少次。
2、输出
考虑一个问题,什么时候输出impossible,什么时候输出次数。
在结果出现impossible的时候,也就是意味着现在出现的这个数是我们bfs所没有找到的,如果说找到了这个数,那么这个数用count计算得到的结果一定是大于0的。
AC代码如下:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#include<string>
using namespace std;
map<string,int>mp;
map<int,int >mmp;
struct xiao
{
int step;
string a;
} mapp[370000];
queue<xiao>q;
char beginn[10],endd[10];//用来存储起始图形数据和结束时候的图形数据
int T;
void bfs(xiao gin)
{
xiao noww,er,nextt;
q.push(gin);
while(!q.empty())
{
er=q.front();
q.pop();
noww=er;
for(int i=1; i<=6; ++i)
{
xiao now=noww;
if(i==1)
swap(now.a[0],now.a[1]),swap(now.a[0],now.a[2]);
if(i==2)
swap(now.a[3],now.a[4]),swap(now.a[3],now.a[5]);
if(i==3)
swap(now.a[6],now.a[7]),swap(now.a[6],now.a[8]);
if(i==4)
swap(now.a[0],now.a[3]),swap(now.a[0],now.a[6]);
if(i==5)
swap(now.a[1],now.a[4]),swap(now.a[1],now.a[7]);
if(i==6)
swap(now.a[2],now.a[5]),swap(now.a[2],now.a[8]);
nextt.a=now.a;
nextt.step=now.step+1;
if(mp.count(nextt.a)>0)
continue;
else
{
mp[nextt.a]=nextt.step;
q.push(nextt);
}
}
}
}
int main()
{
mp["123456789"]=0;
xiao gin;
gin.a="123456789";
gin.step=0;
bfs(gin);
scanf("%d",&T);
while(T--)
{
int cnt=0;
char nnn[10];
for(int i=0; i<3; ++i)
{
scanf("%s",&nnn);
for(int j=0; j<3; ++j)
{
beginn[cnt++]=nnn[j];
}
}
beginn[cnt]='\0';
cnt=0;
for(int i=0; i<3; ++i)
{
scanf("%s",nnn);
for(int j=0; j<3; ++j)
{
endd[cnt++]=nnn[j];
}
}
endd[cnt]='\0';
for(int i=0;i<9;++i)
{
mmp[beginn[i]-'0']=i+1;
}
for(int i=0;i<9;++i)
{
endd[i]=mmp[endd[i]-'0']+'0';
}
for(int i=0;i<9;++i)
beginn[i]=i+'1';
if(mp.count(endd)<=0||mp.count(beginn)<=0)
{
cout<<"impossible"<<endl;
}
else
{
cout<<mp[endd]<<endl;
}
}
return 0;
}