UESTC 485 Game (BFS)

来源:互联网 发布:中国软件杯官网 编辑:程序博客网 时间:2024/06/10 21:07

Description

title

Today I want to introduce an interesting game to you. Like eight puzzle, it is a square board with 99 positions, but it filled by 99 numbered tiles. There is only one type of valid move, which is to rotate one row or column. That is, three tiles in a row or column are moved towards the head by one tile and the head tile is moved to the end of the row or column. So it has 1212 different moves just as the picture left. The objective in the game is to begin with an arbitrary configuration of tiles, and move them so as to get the numbered tiles arranged as the target configuration.

title

Now the question is to calculate the minimum steps required from the initial configuration to the final configuration. Note that the initial configuration is filled with a permutation of 11 to 99, but the final configuration is filled with numbers and * (which can be any number).

Input

The first line of input contains an integer TT (T1000T≤1000), which is the number of data sets that follow.

There are 66 lines in each data set. The first three lines give the initial configuration and the next three lines give the final configuration.

Output

For every test case, you should output Case #k: first, where kk indicates the case number and starts at 11. Then the fewest steps needed. If he can’t move to the end, just output No Solution! (without quotes).

Sample Input


1 2 3 
4 5 6 
7 8 9 
1 2 3 
4 5 6 
7 9 8 
1 2 3 
4 5 6 
7 8 9 
8 * 9 
5 3 7 
2 * *

Sample Output

Case #1: No Solution! 
Case #2: 7

这题一眼广搜题,总共9!种状态,由于T有1000组,所以1000*9!肯定不行,考虑是否可以只BFS一次。

对于不同的第一个输入矩阵,只用把第一个矩阵中的数字和1,2,3,4,5,6,7,8,9对应,即将第一个矩阵变回1,2,3,4,5,6,7,8,9的矩阵,然后根据映射关系处理第二个矩阵,便相当于初始矩阵只有一个,只需广搜预处理即可。

对于矩阵状态保存,刚开始用map,每个矩阵有9位,变成一个9进制的数,结果MLE了,后来思考是否可以有更好的对应关系。

对于一个长度为9排列,假如第一个数字确定,后面的排列可能有8!种,第一个数字有9种,k代表比后面比这个数字小的数有k个,那么这个排列的数位k*8!+后面的排列的处理。所以可以用9!以内的数记录所有的排列,即可。

后来听说这种方式叫康托展开。

#include<stdio.h>#include<string.h>#include<iostream>#include<queue>using namespace std;struct node{    int a[10];}Q,R;int f[]={1,1,2,6,24,120,720,5040,40320},ans[400005],ret,num,use[10],v[10],to[10];int fx[12][3]={{1,2,3},{3,2,1},{4,5,6},{6,5,4},{7,8,9},{9,8,7},{7,4,1},{1,4,7},{2,5,8},{8,5,2},{3,6,9},{9,6,3}};node go(node st,int x,int y,int z){    int tp=st.a[x]; st.a[x]=st.a[y]; st.a[y]=st.a[z]; st.a[z]=tp; return st;}int getvis(node a){    int ret=0,i,j;    for(i=1;i<=9;i++)    {        int seg=0;        for(j=i+1;j<=9;j++) if(a.a[j]<a.a[i]) seg++;        ret+=f[9-i]*seg;    }    return ret;}void bfs(){    int i,j,k;    for(i=0;i<400000;i++) ans[i]=-1;    node now;    for(i=1;i<=9;i++) now.a[i]=i;    ans[getvis(now)]=0;    queue<node> q;    q.push(now);    while(!q.empty())    {        now=q.front(); j=getvis(now);        q.pop();        node tp;        for(i=0;i<12;i++)        {            tp=go(now,fx[i][0],fx[i][1],fx[i][2]);            k=getvis(tp);            if(ans[k]==-1) {ans[k]=ans[j]+1;q.push(tp);}        }    }}int get(){    char s[3];  scanf("%s",s);    if(s[0]=='*') return 0;    num--; return s[0]-'0';}void dfs(int st){    int i,j,k=0;    if(st>num)    {        R=Q;        for(i=1;i<=9;i++) if(R.a[i]==0) R.a[i]=v[++k];        j=getvis(R); if(ans[j]!=-1) ret=min(ret,ans[j]);        return ;    }    for(i=1;i<=9;i++)    {        if(use[i]==0)        {            use[i]=1; v[st]=i; dfs(st+1); use[i]=0;        }    }}int main(){    bfs();    int i,j,T,zz=0;    scanf("%d",&T);    while (T--)    {        ret=1000000000; num=9; memset(use,0,sizeof(use));        memset(to,0,sizeof(to));        for(i=1; i<=9; i++) {scanf("%d",&j);to[j]=i;}        for(i=1; i<=9; i++) Q.a[i]=to[get()],use[Q.a[i]]=1;        dfs(1);        printf("Case #%d: ",++zz);        if(ret==1000000000) printf("No Solution!\n");        else printf("%d\n",ret);    }    return 0;}


0 0
原创粉丝点击