2016年蓝桥杯省赛A组C/C++ 第二题 跳蚱蜢(BFS搜索+状态压缩)

#题目描述:

标题:跳蚱蜢

如图 p1.png 所示: 有9只盘子,排成1个圆圈。 其中8只盘子内装着8只蚱蜢,有一个是空盘。 我们把这些蚱蜢顺时针编号为 1~8

每只蚱蜢都可以跳到相邻的空盘中, 也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。

请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,
并且保持空盘的位置不变(也就是1-8换位,2-7换位,…),至少要经过多少次跳跃?

注意:要求提交的是一个整数,请不要填写任何多余内容或说明文字。

#思路:
目前暂时还没有想到可以手算求解或者dp贪心之类的办法,于是选择暴力枚举搜索状态。
##关于本题搜索方法的技巧:
1.可以将空盘看成是标号为0或者9的盘子。
2.通过取模就可以讲数组首尾相接。
3.把其他盘子跳到空位的操作可以等价看成是把0到盘子分别可以和它左边的两个和右边的两个交换位置,既: now 号位置分别和 now-2 , now-1 , now+1 , now+2 调换位置。这种方法可以简化代码复杂度。
4.把一个描述状态的数组压缩成一个9位十进制数(状压dp思想),从而更方便判断该状态是否出现过。这样也问题就变成了如何从 s=123456789 搜索到 t=876543219。
#代码:

#include
using namespace std;
#define maxn 1000000000
int s=123456789,t=876543219;
bool vis[maxn];
int mo[4]={-2,-1,1,2},a[10];
int get_val(int *a)
{
    int sum=0;
    for(int i=0;i<9;i++)
    {
        sum*=10;
        sum+=a[i];
    }
    return sum;
}
int main()
{
    queueq;
    queued;
    memset(vis,0,sizeof(vis));
    q.push(s);
    vis[s]=1;
    d.push(0);
    while(!d.empty())
    {
        int x=q.front(),cnt=8,now,dd=d.front();;
        while(x>0)
        {
            if(x%10==9)now=cnt;
            a[cnt--]=x%10;
            x/=10;
        }
        for(int i=0;i<4;i++)
        {
            int k=a[now];
            a[now]=a[(now+mo[i]+9)%9];
            a[(now+mo[i]+9)%9]=k;
            int val=get_val(a);
            if(!vis[val])
            {
                vis[val]=1;
                if(val==t)
                {
                    printf("ans=%d\n",dd+1);
                    return 0;
                }
                //printf("%d\n",val);
                q.push(val);
                d.push(dd+1);
            }
            k=a[now];
            a[now]=a[(now+mo[i]+9)%9];
            a[(now+mo[i]+9)%9]=k;
        }
        q.pop();
        d.pop();
    }
}

你可能感兴趣的:(搜索,暴力)