神奇密碼鎖 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);
    }

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章