Aizu 0121 Seven Puzzle

7パズルは8つの正方形のカードとこれらのカードがぴたりと収まる枠を使って行います。それぞれのカードは互いに区別できるように、0,1,2....7と番号がつけられています。枠には、縦に2個、横に4個のカードを並べることができます。

7パズルを始めるときには、まず枠にすべてのカードを入れます。枠のなかで0のカードだけは、上下左右に隣接するカードと位置を交換することができます。たとえば、枠の状態が図( a )のときに、0のカードの右に隣接した、7のカードと位置を交換すれば、図( b )の状態になります。あるいは、図( a )の状態から0のカードの下に隣接した2のカードと位置を交換すれば図( c )の状態になります。カードの位置を入れ替える操作はこれだけが許されます。図( a )の状態で0のカードと上下左右に隣接するカードは7と2のカードだけなので、これ以外の位置の入れ替えは許されません。

ゲームの目的は、カードをきれいに整列して図( d )の状態にすることです。最初の状態を入力とし、カードをきれいに整列するまでに、必要な最小手数を出力して終了するプログラムを作成してください。ただし、入力されたカードの状態からは図( d )の状態に移ることは可能であるとします。

入力データは、1行に8つの数字が与えられます。これらは、最初の状態のカードの並びを表します。図( a )の数字表現は0,7,3,4,2,5,1,6に、図( c )は2,7,3,4,0,5,1,6となります。

図( a ) 0,7,3,4,2,5,1,6の場合図( b ) 7,0,3,4,2,5,1,6の場合


図( c ) 2,7,3,4,0,5,1,6の場合図( d ) 0,1,2,3,4,5,6,7(最終状態)

Input

1つ目のパズルの状態(整数;空白区切り)
2つ目のパズルの状態(整数;空白区切り)
     :
     :

与えられるパズルの数は1000以下です。

Output

1つ目のパズルの状態から最終状態へ移行する最小手数(整数)
2つ目のパズルの状態から最終状態へ移行する最小手数(整数)
            :
            :

Sample Input

0 1 2 3 4 5 6 7
1 0 2 3 4 5 6 7
7 6 5 4 3 2 1 0

Output for the Sample Input

0
1

28

这道题主要的解题思路是预处理,在程序执行前先把所有的可能性存储。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<map>
#include<iostream>
#include<queue>
using namespace std;
map<string,int>gmap;
int a[2][4];
int b[2][4];
int vis[4][2]={1,0,0,1,0,-1,-1,0};
struct text
{
    int a[2][4];
}st,tt,start;
queue<text> q;
char s[9];
char ss[9];
int temp=0;
int cnt=1;
bool check(int x,int y)
{
    if(x<0||y<0||x>=2||y>=4)
        return false;
    return true;
}
void bfs()
{
    while(!q.empty())
    {
        st=q.front();
        q.pop();
        int x,y;
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<4;j++)
            {
                if(st.a[i][j]==0)
                {
                   x=i;
                   y=j;
                }
                a[i][j]=st.a[i][j];
                ss[i*4+j]=st.a[i][j]+'0';
            }

        }
<span style="white-space:pre">	</span>//将结果存在map里
        for(int i=0;i<4;i++)
        {
            for(int j=0;j<2;j++)
            {
                int k=x+vis[i][0];
                int l=y+vis[i][1];
                if(check(k,l))
                {
                    int xx=a[x][y];
                    a[x][y]=a[k][l];
                    a[k][l]=xx;
                    for(int i=0;i<2;i++)
                    {
                        for(int j=0;j<4;j++)
                        {
                            s[i*4+j]=a[i][j]+'0';
                            tt.a[i][j]=a[i][j];
                        }
                    }
                    s[8]='\0';
                    if(!gmap[s]>0)
                    {
                        gmap[s]=gmap[ss]+1;
                        q.push(tt);
                    }
                    xx=a[x][y];
                    a[x][y]=a[k][l];
                    a[k][l]=xx;
                }
            }
        }
    }
}
int main()
{
    for(int i=0;i<8;i++)
        a[i/4][i%4]=i;
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<4;j++)
            start.a[i][j]=a[i][j];
    }
    for(int i=0;i<2;i++)
        {
            for(int j=0;j<4;j++)
            {
                s[i*4+j]=start.a[i][j]+'0';
            }
        }
    s[8]='\0';
    gmap[s]=1;
    q.push(start);
    bfs();//在程序执行前处理
    while(~scanf("%d",&a[0][0]))
    {
        for(int i=1;i<4;i++)
            scanf("%d",&a[0][i]);
        for(int i=0;i<4;i++)
            scanf("%d",&a[1][i]);
        for(int i=0;i<2;i++)
        {
            for(int j=0;j<4;j++)
            {
                s[i*4+j]=a[i][j]+'0';
            }
        }
        s[8]='\0';
       // puts(s);
        printf("%d\n",gmap[s]-1);//直接输出map里的值
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值