神奇密码锁 bfs

问题 D: 神奇密码锁

时间限制: 2 Sec  内存限制: 128 MB
提交: 204  解决: 53
[ 提交][ 状态][ 讨论版]

题目描述

 小明忘记了旅行箱上的密码,现在他想自己暴力弄出密码来,但他又想知道最从一个数字到另一个数字最少需要多少步,现在请你帮忙。

另外,小明的密码箱很奇怪,只有四位数,上面的数字只有1到9,每次只能让每位数加1或者减1。按常识我们可以知道从1到9只需要减1,从9到1只需要加1。此外,你还能交换相邻的两个数字。如1234可以在一步后变成2134,但不能变成4231。

输入

第一行有一个整数:T,代表有多少组测试数据。

接下来T行,每行有两个整数(都是四位数),第一个是初状态,第二个是目标状态。

输出

每组数据输出一个整数,占一行。

样例输入

21234 21441111 9999

样例输出

24

提示

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
int st[6],goal[6];
char st0[6],goal0[6];
int visti[10000];
int ans;
struct data {
    int s[6];
    int sum;
};
//queue <data> que;
bool check(int s[])
{
    int t=(s[0])*1000+(s[1])*100+(s[2])*10+(s[3]);
    if(!visti[t]){
        visti[t]=1;//标记为已访问
        return true;
    }
    return false;
}
void bfs() {
    queue <data> que;
    data p;
    memcpy(p.s,st,sizeof(st));
    p.sum=0;
    if(check(p.s))
      que.push(p);
    while(!que.empty()) {
        p=que.front();
        que.pop();
        if(!memcmp(p.s,goal,sizeof(goal))) {
            ans=p.sum;
            return ;
        }
        for(int j=0; j<4; j++) {
            int t=p.s[j];
            p.sum++;
            if(p.s[j]<9) p.s[j]++;
            else p.s[j]=1;
            if(check(p.s))
                que.push(p);
            p.s[j]=t;
            if(p.s[j]>1) p.s[j]--;
            else p.s[j]=9;
            if(check(p.s))
                que.push(p);
            p.s[j]=t;
            if(j<3) {
                int temp;
                temp=p.s[j+1];
                p.s[j+1]=p.s[j];
                p.s[j]=temp;
                if(check(p.s))
                    que.push(p);
                p.s[j]=t;
                p.s[j+1]=temp;
            }
            p.sum--;
        }
    }

}
int main() {
    int n;
    scanf("%d",&n);
    while(n--) {
        ans=0;
        scanf("%s%s",st0,goal0);
        for(int i=0;i<4;i++)
        {
            st[i]=st0[i]-'0';
            goal[i]=goal0[i]-'0';
        }
        memset(visti,0,sizeof(visti));
        bfs();
        printf("%d\n",ans);
    }

}


下面的代码,想尝试用A*算法,写的,但是在求H(n)的函数那里找不到一个好的办法,所以导致超时了。留在这里日后思考。如果有路过的大神知道如何修改,可以私聊我。QQ:751479173

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int st[6],goal[6];
char st0[6],goal0[6];
int visti[10000];
int ans;
struct data {
    int s[6];
    int sum;
    int g,h,f;
    bool operator < (const data & k) const {     //重载比较运算符
        if(f==k.f)
            return g>k.g;
        return f > k.f;
    }
};
//queue <data> que;
bool check(int s[]) {
    int t=(s[0])*1000+(s[1])*100+(s[2])*10+(s[3]);
    if(!visti[t]) {
        visti[t]=1;//标记为已访问
        return true;
    }
    return false;
}
int bianhao(int s[]) {
    int t;
    return  t=(s[0])*1000+(s[1])*100+(s[2])*10+(s[3]);
}

int wrongPlaceNum(int a[]) { //求不在位的数字个数
    int cnt=0;
    for(int i=0; i<4; i++)
        if(a[i]!=goal[i]) cnt++;
    return cnt;
}

void bfs() {
    priority_queue <data> que;
    data p,q;
    memcpy(q.s,st,sizeof(st));
    q.sum=p.g=0;
    q.h=wrongPlaceNum(q.s);
    q.f=q.g+q.h;
    if(check(q.s))
        que.push(q);
    while(!que.empty()) {
        q=que.top();
        que.pop();
        if(!memcmp(q.s,goal,sizeof(goal))) {
            ans=q.sum;
            return ;
        }
        for(int j=0; j<4; j++) {
            memcpy(&p,&q,sizeof(q));
            if(p.s[j]<9) p.s[j]++;
            else p.s[j]=1;
            if(check(p.s)) {
                p.g=p.g+1;
                p.h=wrongPlaceNum(p.s);
                p.f=p.g+p.h;
                p.sum++;
                que.push(p);
            }
            memcpy(&p,&q,sizeof(q));
            if(p.s[j]>1) p.s[j]--;
            else p.s[j]=9;
            if(check(p.s)) {
                p.g=p.g+1;
                p.h=wrongPlaceNum(p.s);
                p.f=p.g+p.h;
                p.sum++;
                que.push(p);
            }
            memcpy(&p,&q,sizeof(q));
            if(j<3) {
                int temp;
                temp=p.s[j+1];
                p.s[j+1]=p.s[j];
                p.s[j]=temp;
                if(check(p.s)) {
                    p.g=p.g+1;
                    p.h=wrongPlaceNum(p.s);
                    p.f=p.g+p.h;
                    p.sum++;
                    que.push(p);
                }
            }
            memcpy(&p,&q,sizeof(q));
        }
    }

}
int main() {
    int n;
    scanf("%d",&n);
    while(n--) {
        ans=0;
        scanf("%s%s",st0,goal0);
        for(int i=0; i<4; i++) {
            st[i]=st0[i]-'0';
            goal[i]=goal0[i]-'0';
        }
        memset(visti,0,sizeof(visti));
        bfs();
        printf("%d\n",ans);
    }

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值