POJ3221 Diamond Puzzle(BFS:最短路)

POJ3221 Diamond Puzzle(BFS:最短路)

http://poj.org/problem?id=3221

题意:

        如下的平面魔方,现在给你一个魔方的初态,比如3图,要你算出从3图移动到2图的状态需要多少步。其中每步移动只能交换空格(0那格)与它相邻的格子的内容。

分析:

       首先我们要想好怎么表示一个状态,我们用一个人char s[10]来表示状态,比如2图的状态是0123456.

       然后我们用BFS扩展队列中节点的后续状态,并且计算到新状态的最短距离。但是这里我们还需要判断新状态以前是否出现过,所以我们用hash表来判重,其实与前几道题目基本是一样的思路,不过就是改了下数据形式。hash表我们可以自己实现,也可以直接用STL中的map<string,int>hash来表示。

       注意:由于题目有很多组数组,所以我们事先求出从0123456到所有可能状态的距离,然后对于题目的每个询问输出即可。(否则超时)

       本题我用的是STL中的map来作为hash查重,且用的STL中的queue,没有自己写hash和队列,代码短了(正常情况下本题应该在100行代码以上,但是下面只写了60几行),速度也不慢,关键错误少了,直接一次AC。STL中的东西在一定情况下还是推荐使用的。

AC代码:

#include<cstring>
#include<cstdio>
#include<string>
#include<map>
#include<queue>
using namespace std;
const int maxn=10000;
int d[7][5]={{2,4,6,-1},{2,6,-1},{0,1,3,-1},{2,4,-1},{0,3,5,-1},{4,6,-1},{0,1,5,-1}};
//d[i][j]=x 表示原始标记的i格能与原始标记的x格交换
map<string ,int> vis;//判断当前状态是否出现过,map中的int初值为0,也即如果对应string不存在,那么就是int为0值
map<string ,int> ans;//当前状态出现的最小操作步数
struct Node
{
    char s[10];//保存状态
    int dist;//最小步数
};
queue<Node> Q;
char s[10]="0123456";
void BFS()
{
    Node node1;
    strcpy(node1.s,s);
    node1.dist=0;
    Q.push(node1);
    ans[string(s)]=0;
    vis[string(s)]=1;

    while(!Q.empty())
    {
        Node node=Q.front();Q.pop();
        int pos;//pos表状态中0的位置
        for(int i=0;node.s[i];i++)if(node.s[i]=='0') {pos=i;  break;}

        for(int i=0;d[pos][i]!=-1;i++)//依次遍历当前0位置能交换的对应位置
        {
            int npos=d[pos][i];//pos能交换的对应位置为npos
            Node node2= node;
            node2.s[pos]=node.s[npos];
            node2.s[npos]=node.s[pos];
            node2.dist =1+node.dist;
            if(vis[string(node2.s)]==0)//此状态之前未出现过
            {
                vis[string(node2.s)]=1;
                ans[string(node2.s)]=node2.dist;
                Q.push(node2);
            }
        }
    }
}
int main()
{
    BFS();
    int T; scanf("%d",&T);
    while(T--)
    {
        char str[10];
        scanf("%s",str);
        if(strcmp(str,s)==0) printf("0\n");
        else printf("%d\n",ans[string(str)]==0?-1:ans[string(str)]);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值