1. 程式人生 > >hdu1043八數碼 bfs 打表/雙向bfs/A*+康託判重+逆序奇偶剪枝

hdu1043八數碼 bfs 打表/雙向bfs/A*+康託判重+逆序奇偶剪枝

寫之前拜讀了這篇文章:八數碼的八境界

個人覺得寫順序為

一(可寫可不寫,介意找工作的的人最好試試這種寫法)-->三 -->二 -->四 -> 六-->八

境界一、逆向廣搜+STL

多組輸入輸出,可以想到打表,bfs時間複雜度為9!,查詢複雜度為O(1)

判重方法:

set<node>vis;
set紅黑樹實現,查詢效率log(n);總的效率nlog(n)(10^6),肯定會TLE
#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <queue>
using namespace std;

struct node{
public:
    node(string s, string pa, int p):sty(s),path(pa),pos(p){}
public:
    string sty;
    string path;
    int pos;
};
map<string,string>res;
set<string>vis;
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
string dir("durl");//ÄæÏòËÑË÷

bool check(int x,int y)
{
    if(x<0||x>2||y<0||y>2)return false;
    else return true;
}

void bfs(){
    queue<node>q;
    node n("12345678x","",8);
    vis.insert("12345678x");
    q.push(n);
    while(!q.empty()){
        n=q.front();
        q.pop();
        int x=n.pos/3;
        int y=n.pos%3;
        for(int i=0;i<4;++i){
            int newx=x+dx[i];
            int newy=y+dy[i];
            if(!check(newx,newy))continue;
            int newpos=newx*3+newy;
            swap(n.sty[n.pos],n.sty[newpos]);
            if(vis.find(n.sty)!=vis.end()){
                swap(n.sty[n.pos],n.sty[newpos]);
                continue;
            }
            else{
                q.push(node(n.sty,dir[i]+n.path,newpos));
                vis.insert(n.sty);
                res[n.sty]=dir[i]+n.path;
                swap(n.sty[n.pos],n.sty[newpos]);
            }
        }
    }

}

int main()
{
    //freopen("in.txt","r",stdin);
    string in;
    string tmp;
    int spos;
    res[in]="";
    bfs();
    while(cin>>tmp){
        in.push_back(tmp[0]);
        for(int i=1;i<9;++i){
            cin>>tmp;
            in.push_back(tmp[0]);
        }
        //cout<<in<<endl;
        if(res[in]=="")printf("unsolvable\n");
        else cout<<res[in]<<endl;
    }

    return 0;
}


這份程式碼由於將path放在node裡面,也會MLE

境界三、逆向廣搜+雜湊+打表

     是對境界一的改進,set判重改進為cantor判重

     從目標狀態123456780反向搜尋,記錄所有可達狀態的路徑

     用了兩種記錄路徑的方法,一種是用char path[maxn][36],每個節點維護一個len變數;第二種是每個狀態記錄上一個狀態parent,

path[cur.status].from=parent.stauts
上面是第二種方法,下面是第一種方法

程式碼如下

//char path[maxn][42]

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#include <string>
#include <cstring>

using namespace std;
const int maxn = 362880 + 5;
int fac[9];
char path[maxn][42];
int vis[maxn];

int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };
char dir[]="durl";

struct node
{
public:
    node(int p, int s, int l) :pos(p), status(s), len(l){}
public:
    int pos;
    int status;
    int len;
};

void calFac(int *f, int n)
{
    f[0] = 1;
    for (int i = 1; i<n; ++i)f[i] = f[i - 1] * i;
}
int encodeCantor(int *s)
{
    int i, j, num, temp;
    num = 0;
    for (i = 0; i<9; ++i){
        temp = 0;
        for (j = i + 1; j<9; ++j){
            if (s[j]<s[i])
                temp++;
        }
        num += fac[9 - 1 - i] * temp;
    }
    return num;
}

void decodeCantor(int *s, int val)
{
    bool flag[10];
    memset(flag, 0, sizeof(flag));
    for (int i = 0; i<9; ++i){
        int _rank = val / fac[8 - i];
        for (int j = 0; j <= _rank; ++j){
            if (flag[j]){
                _rank++;
            }
        }
        s[i] = _rank;
        flag[_rank] = true;;
        val = val%fac[8 - i];
    }
}

bool check(int x, int y)
{
    if (x<0 || y<0 || x>2 || y>2)return false;
    else return true;
}

void bfs()
{
    queue<node>q;
    int s[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
    node n(8, encodeCantor(s),0);
    vis[n.status] = 1;
    path[n.status][0] = '\0';
    q.push(n);
    while (!q.empty()){
        n = q.front();
        q.pop();
        int x = n.pos / 3; int y = n.pos % 3;
        for (int i = 0; i<4; ++i){
            int newx = x + dx[i];
            int newy = y + dy[i];
            if (!check(newx, newy))continue;
            int newpos = newx * 3 + newy;
            decodeCantor(s, n.status);
            swap(s[n.pos], s[newpos]);
            int nstatus = encodeCantor(s);
            if (!vis[nstatus]){
                for (int i = 0; i < n.len; i++)path[nstatus][i] = path[n.status][i];
                path[nstatus][n.len] = dir[i];
                path[nstatus][n.len+1] = '\0';
                vis[nstatus] = 1;
                q.push(node(newpos, nstatus,n.len+1));
            }
            swap(s[n.pos], s[newpos]);
        }

    }

}

void init()
{
    calFac(fac, 9);
    memset(vis, 0, sizeof(vis));
    //cout<<fac[8]*9<<endl;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    init();
    bfs();

    string tmp;
    int in[9];
    while (cin >> tmp){
        if (tmp[0] == 'x')in[0] = 0;
        else in[0] = tmp[0] - '0';
        for (int i = 1; i<9; ++i){
            cin >> tmp;
            if (tmp[0] == 'x')in[i] = 0;
            else in[i] = tmp[0] - '0';
        }
        int status = encodeCantor(in);
        if (!vis[status])cout << "unsolvable" << endl;
        else {
            int len = strlen(path[status]);
            for (int i = len - 1; i >= 0; --i)printf("%c", path[status][i]);
            printf("\n");
        }
    }

    return 0;
}

第二種記錄路徑的方法,速度更快,記憶體更小

//記錄上一個stauts

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#include <string>
#include <cstring>

using namespace std;
const int maxn = 362880 + 5;
int fac[9];
int vis[maxn];

int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };
char dir[]="durl";

struct node
{
public:
    node(int p, int s) :pos(p), status(s){}
public:
    int pos;
    int status;
};

struct path
{
public:
    int from, dir;
}p[maxn];

void calFac(int *f, int n)
{
    f[0] = 1;
    for (int i = 1; i<n; ++i)f[i] = f[i - 1] * i;
}
int encodeCantor(int *s)
{
    int i, j, num, temp;
    num = 0;
    for (i = 0; i<9; ++i){
        temp = 0;
        for (j = i + 1; j<9; ++j){
            if (s[j]<s[i])
                temp++;
        }
        num += fac[9 - 1 - i] * temp;
    }
    return num;
}

void decodeCantor(int *s, int val)
{
    bool flag[10];
    memset(flag, 0, sizeof(flag));
    for (int i = 0; i<9; ++i){
        int _rank = val / fac[8 - i];
        for (int j = 0; j <= _rank; ++j){
            if (flag[j]){
                _rank++;
            }
        }
        s[i] = _rank;
        flag[_rank] = true;;
        val = val%fac[8 - i];
    }
}

bool check(int x, int y)
{
    if (x<0 || y<0 || x>2 || y>2)return false;
    else return true;
}


void bfs()
{
    queue<node>q;
    int s[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
    node n(8, encodeCantor(s));
    vis[n.status] = 1;
    p[n.status].from = -1;
    q.push(n);
    while (!q.empty()){
        n = q.front();
        q.pop();
        int x = n.pos / 3; int y = n.pos % 3;
        for (int i = 0; i<4; ++i){
            int newx = x + dx[i];
            int newy = y + dy[i];
            if (!check(newx, newy))continue;
            int newpos = newx * 3 + newy;
            decodeCantor(s, n.status);
            swap(s[n.pos], s[newpos]);
            int nstatus = encodeCantor(s);
            if (!vis[nstatus]){
                p[nstatus].from = n.status;
                p[nstatus].dir = i;
                vis[nstatus] = 1;
                q.push(node(newpos, nstatus));
            }
            swap(s[n.pos], s[newpos]);
        }

    }

}

void print(int s)
{
    while (p[s].from != -1)
    {
        printf("%c", dir[p[s].dir]);
        s = p[s].from;
    }
    printf("\n");
}

void init()
{
    calFac(fac, 9);
    memset(vis, 0, sizeof(vis));
}

int main()
{
    //freopen("in.txt", "r", stdin);
    init();
    bfs();

    string tmp;
    int in[9];
    while (cin >> tmp){
        if (tmp[0] == 'x')in[0] = 0;
        else in[0] = tmp[0] - '0';
        for (int i = 1; i<9; ++i){
            cin >> tmp;
            if (tmp[0] == 'x')in[i] = 0;
            else in[i] = tmp[0] - '0';
        }
        int status = encodeCantor(in);
        if (!vis[status])cout << "unsolvable" << endl;
        else {
            print(status);
        }
    }

    return 0;
}

境界四、雙向BFS+康託判重+剪枝


如圖,雙向bfs可以節約一半的時間和空間,注意境界一複雜度時9!,現在是9!/2,還不夠快。

故注意進行奇偶剪枝,否則會TLE

剪枝原理:

       逆序數:對於n個不同的元素,先規定各元素之間有一個標準次序(例如n個 不同的自然數,可規定從小到大為標準次序),於是在這n個元素的任一排列中,當某兩個元素的先後次序與標準次序不同時,就說有1個逆序。逆序對的總數稱為逆序數

       只要終止狀態和起始狀態的逆序數(空的位置不算)奇偶性不同,就一定不能達到目標狀態。

       分析:向左或者向右移動,逆序數的奇偶行不變....0,xt,xt+1...,將.0和xt交換,奇偶性是不變的

       對 x1  x2  x3

           x4   x5  x6

           x7   0    x8

      將0和x5交換,x1  x2  x3  x4   x5  x6 x7   0    x8,下面分三種情況

     a)若 x5>x6 && x5> x7,則逆序數+2

     a)若 x5 <x6 && x5<x7,則逆序數-2

     a)若 x5 在6 和x7之間,則逆序數不變

通過以上分析可知:只有起始狀態可終止狀態逆序數奇偶性相同才能轉換

雙向bfs,採用兩個佇列q1和q2,一個從起始狀態向目標狀態擴充套件,另一個從目標狀態像起始狀態擴充套件

判別重可以採用

int vis[manx];//q1為1,q2為2

//可以用
bool vis1[maxn],vis2[maxn];

輸出路徑時

q1的另用一個數組記錄下來

char tmp[36]; int len = 0;
    while (p1[s]!= -1){
        tmp[len++] = dir1[d1[s]];
        s = p1[s];
    }
q2利用和境界三一樣的方法 程式碼如下
#include <stdio.h>
#include <queue>
#include <memory.h>
using namespace std;

const int maxn = 362880 + 5;
char *dir1 = "udlr";
char *dir2 = "durl";

int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };

struct node
{
public:
    int status, pos;
};

int p1[maxn], p2[maxn];
int d1[maxn], d2[maxn];
bool vis1[maxn],vis2[maxn];
int fac[9];
void init()
{
    fac[0] = 1;
    for (int i = 1; i<9; ++i){
        fac[i] = i*fac[i - 1];
    }

}

int encodeCantor(int *s)
{
    int _rank, sum = 0;
    for (int i = 0; i < 9; ++i){
        _rank = 0;
        for (int j = i + 1; j<9; ++j){
            if (s[i]>s[j])_rank++;
        }
        sum += fac[8 - i] * _rank;
    }
    return sum;
}

void decodeCantor(int *arr, int s)
{
    bool flag[9];
    memset(flag, 0, sizeof(flag));
    for (int i = 0; i<9; ++i){
        int _rank = s / fac[8 - i];
        for (int j = 0; j <= _rank; ++j){
            if (flag[j])_rank++;
        }
        arr[i] = _rank;
        flag[_rank] = 1;
        s = s%fac[8 - i];
    }
}

bool check(int x, int y)
{
    if (x<0 || y<0 || x>2 || y>2)return false;
    else return true;
}

void print(int status)
{
    int s = status;
    char tmp[36]; int len = 0;
    while (p1[s]!= -1){
        tmp[len++] = dir1[d1[s]];
        s = p1[s];
    }
    s = status;
    for (int i = len - 1; i >= 0; i--)printf("%c", tmp[i]);
    while (p2[s] != -1){
        printf("%c", dir2[d2[s]]);
        s = p2[s];
    }
    printf("\n");
}

void bfs(int init_pos, int init_status)
{
    queue<node>q1, q2;
    memset(vis1, 0, sizeof(vis1));
    memset(vis2, 0, sizeof(vis2));
    int arr[9];
    int aim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
    int aim_s = encodeCantor(aim);
    node n;
    n.status=init_status;
    n.pos=init_pos;
    q1.push(n);
    n.status=aim_s;
    n.pos=8;
    q2.push(n);

    node cur;
    node next;

    p1[init_status] = -1;
    p2[aim_s] = -1;
    vis1[init_status] = 1;
    vis2[aim_s] = 1;
    int flag;
    while (!q1.empty() || !q2.empty()){
        if (!q1.empty() && (q2.empty() || q1.size() <= q2.size())) {//選擇較少的擴充套件,效率較高
            flag = 1;
            cur = q1.front();
            q1.pop();
            if (vis2[cur.status]){
                print(cur.status);
                return;
            }
        }
        else {
            flag = 2;
            cur = q2.front();
            q2.pop();
            if (vis1[cur.status]){
                print(cur.status);
                return;
            }
        }
        decodeCantor(arr, cur.status);
        int x = cur.pos / 3; int y = cur.pos % 3;
        for (int i = 0; i<4; ++i){

            int nx = x + dx[i]; int ny = y + dy[i];
            if (!check(nx, ny))continue;
            int newpos = nx * 3 + ny;
            swap(arr[cur.pos], arr[newpos]);
            int nstatus = encodeCantor(arr);
            if (flag == 1 && !vis1[nstatus]){
                p1[nstatus] = cur.status;
                d1[nstatus] = i;
                if (vis2[nstatus]){
                    print(nstatus);
                    return;
                }
                else {
                    vis1[nstatus] = 1;
                    next.status=nstatus;
                    next.pos=newpos;
                    q1.push(next);
                }
            }
            else if (flag == 2 && !vis2[nstatus]){
                p2[nstatus]= cur.status;
                d2[nstatus] = i;
                if (vis1[nstatus]){
                    print(nstatus);
                    return;
                }
                else{
                    vis2[nstatus] = 1;
                    next.status=nstatus;
                    next.pos=newpos;
                    q2.push(next);
                }
            }

            swap(arr[cur.pos], arr[newpos]);
        }

    }
    return;
}

//奇偶剪枝
bool pruning(int *arr){
    int flag = 0;
    for (int i = 0; i<9; ++i){
        if (arr[i] == 0) continue;
        for (int j = i + 1; j<9; ++j){
            if (arr[j] && arr[i]>arr[j]) flag++;
        }
    }
    if (flag % 2) return true;
    return false;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    char tmp[3];
    int in[9];
    int pos;
    init();
    while (scanf("%s", tmp) != EOF){

        if (tmp[0] == 'x'){
            in[0] = 0;
            pos = 0;
        }
        else in[0] = tmp[0] - '0';
        for (int i = 1; i<9; ++i){
            scanf("%s", tmp);
            if (tmp[0] == 'x'){
                in[i] = 0;
                pos = i;
            }
            else in[i] = tmp[0] - '0';
        }
        int status = encodeCantor(in);
        if (pruning(in))printf("unsolvable\n");
        else {
            bfs(pos, status);
        }
    }
    return 0;
}

境界六、A*+cantor判重+曼哈頓距離

境界五和境界六差不多,就是啟發式函式使用的不一樣,直接寫了境界六

啟發式演算法的估價函式為 f(n) = g(n) + h(n)

     G 表示從起點 A 移動到網格上指定方格的移動耗費 (可沿斜方向移動).

     H 表示從指定的方格移動到終點 B 的預計耗費 (H 有很多計算方法, 這裡我們設定只可以上下左右移動).

A*演算法的估價函式可以表示為

       f'(n) = g'(n) + h'(n) 
       f’(n)是估價函式,g’(n)是起點到終點的最短路徑值,h’(n)是n到目標的最斷路經的啟發值。由 於這個f’(n)其實是無法預先知道的,所以我們用估價函式f(n)做近似。g(n)代替g’(n),但 g(n)>=g’(n) 才可(大多數情況下都是滿足的,可以不用考慮),h(n)代替h’(n),但h(n)<=h’(n)才可(這一點特別的重 要)。

這裡的G指的是bfs擴充套件的層數,因為一層就是一步

           H指的是當前位置到終點的曼哈頓距離

計算曼哈頓距離的函式為

int getH(int *arr)
{
    int x, y;
    int h = 0;
    for (int i = 0; i<9; ++i){
        if (arr[i]){
            x = i / 3;
            y = i % 3;
            h += abs(x - tx[arr[i]]) + abs(y - ty[arr[i]]);//tx,ty分別表示arr[i]的目標位置座標
        }
    }
    return h;
}


上程式碼

#include <iostream>
#include <stdio.h>
#include <queue>
#include <memory.h>
#include <stdlib.h>
using namespace std;
const int maxn = 362880 + 5;
int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320 };
char *dir = "udlr";
int dx[] = { -1, 1, 0, 0 };
int dy[] = { 0, 0, -1, 1 };
bool vis[maxn];

struct node
{
    int status, pos;
    int g, h;
    bool operator<(const node&n)const{
        return (g + h)>(n.g + n.h);
    }
};

struct path
{
    int from, dir;
}p[maxn];

int tx[] = { 2, 0, 0, 0, 1, 1, 1, 2, 2 };
int ty[] = { 2, 0, 1, 2, 0, 1, 2, 0, 1 };

int encodeCantor(int *arr)
{
    int sum = 0;
    for (int i = 0; i<9; ++i){
        int _rank = 0;
        for (int j = i + 1; j<9; ++j){
            if (arr[i]>arr[j])_rank++;
        }
        sum += _rank*fac[8 - i];
    }
    return sum;
}

void decodeCantor(int *arr, int val)
{
    int flag[9], _rank;
    memset(flag, 0, sizeof(flag));
    for (int i = 0; i<9; ++i){
        _rank = val / fac[8 - i];
        for (int j = 0; j <= _rank; ++j){
            if (flag[j])_rank++;
        }
        arr[i] = _rank;
        flag[_rank] = 1;
        val = val%fac[8 - i];
    }
}

int getH(int *arr)
{
    int x, y;
    int h = 0;
    for (int i = 0; i<9; ++i){
        if (arr[i]){
            x = i / 3;
            y = i % 3;
            h += abs(x - tx[arr[i]]) + abs(y - ty[arr[i]]);
        }
    }
    return h;
}

bool pruning(int *arr)
{
    int sum = 0;
    for (int i = 0; i<9; ++i){
        if (!arr[i])continue;
        for (int j = i + 1; j<9; ++j){
            if (arr[j]&&arr[i]>arr[j])sum++;
        }
    }
    if (sum % 2)return true;
    else return false;
}

bool check(int x, int y)
{
    if (x<0 || y<0 || x>2 || y>2)return false;
    else return true;
}

void A_star(int *arr)
{
    int aim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
    int aim_s = encodeCantor(aim);
    priority_queue<node>q;
    memset(vis, 0, sizeof(vis));
    node cur, next;
    int status = encodeCantor(arr);
    for (int i = 0; i<9; ++i){
        if (!arr[i]){
            cur.pos = i;
            break;
        }
    }
    cur.status = status;
    cur.g = 0;
    cur.h = getH(arr);
    q.push(cur);
    p[status].from = -1;
    vis[status] = 1;
    while (!q.empty()){
        cur = q.top();
        q.pop();
        decodeCantor(arr, cur.status);
        if (cur.status == aim_s){
            int s = cur.status, len = 0;
            char res[maxn];
            while (p[s].from != -1){
                res[len++] = dir[p[s].dir];
                s = p[s].from;
            }
            for (int i = len - 1; i >= 0; i--){
                printf("%c", res[i]);
            }
            printf("\n");
            return;
        }
        else{

            int x = cur.pos / 3; int y = cur.pos % 3;
            for (int i = 0; i<4; ++i){
                int nx = x + dx[i];
                int ny = y + dy[i];
                if (!check(nx, ny))continue;
                int newpos = nx * 3 + ny;
                swap(arr[newpos], arr[cur.pos]);
                int nstatus = encodeCantor(arr);
                if (!vis[nstatus]){
                    next.status = nstatus;
                    next.pos = newpos;
                    next.g = cur.g + 1;
                    next.h = getH(arr);
                    p[next.status].from = cur.status;
                    p[next.status].dir = i;
                    vis[next.status] = 1;
                    q.push(next);
                }
                swap(arr[newpos], arr[cur.pos]);
            }
        }
    }
    printf("unsolvable\n");

}

int main()
{
    //freopen("in.txt", "r", stdin);
    char tmp[5];
    int in[9];
    while (scanf("%s", tmp) != EOF){
        if (tmp[0] == 'x')in[0] = 0;
        else in[0] = tmp[0] - '0';
        for (int i = 1; i<9; ++i){
            scanf("%s", tmp);
            if (tmp[0] == 'x')in[i] = 0;
            else in[i] = tmp[0] - '0';
        }
        //int status=encodeCantor(in);
        if (pruning(in))printf("unsolvable\n");
        else A_star(in);
    }
    return 0;
}




相關推薦

hdu1043數碼 bfs /雙向bfs/A*++剪枝

寫之前拜讀了這篇文章:八數碼的八境界 個人覺得寫順序為 一(可寫可不寫,介意找工作的的人最好試試這種寫法)-->三 -->二 -->四 -> 六-->八 境界一、逆向廣搜+STL 多組輸入輸出,可以想到打表,bfs時間複雜度為9!,查詢複雜度

hdu1043 Eight(A*/雙向BFS/單項BFS+展開)

題意描述:經典八數碼問題,給定八數碼的初始序列,求經過u、r、l、d四種操作到達1 2 3 4 5 6 7 8 x的狀態,打印出操作序列? 解題思路:A*/雙向BFS/單項BFS打表+康託展開   202msAC 方法一:BFS逆向打表+康託展開:從1 2 3 4 5

HDU 1043 Eight(反向BFS++托展開)

front int 二維 -i 轉換成 思路 離散化 strlen acm 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 題目大意:傳統八數碼問題 解題思路:就是從“12345678x”這

hdu 6253 (bfs

連結:http://acm.hdu.edu.cn/showproblem.php?pid=6253 題意: 馬可以往一個方向走兩步,然後轉個彎走一步,這樣算一次動作,求問馬n次動作後,能到達多少個點,重複到達的點只算一次。 思路: 一開始完全沒思路,畫圖找了半天把自己畫崩了,後面看到資料和樣例感覺這應

poj 1077 Eight (數碼問題——A*+cantor展開+剪枝)

www. += 優先級 pri 排列 view 組成 esp 改變 題目來源: http://poj.org/problem?id=1077 題目大意: 給你一個由1到8和x組成的3*3矩陣,x每次可以上下左右四個方向交換。求一條路徑,得到12345678x這樣的矩陣。

HDU_1043 Eight 【逆向BFS + 展開 】【A* + 展開 】

一、題目 http://acm.hdu.edu.cn/showproblem.php?pid=1043 二、兩種方法 該題很明顯,是一個八數碼的問題,就是9宮格,裡面有一個空格,外加1~8的數字,任意一種情況,如果能通過移動空格使數碼組成 1 2 3 4 5 6 7 8 0  的形式,就輸

HDU1097暴力找規律a^b

A hard puzzle Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth

HDU1043 Eight A +

The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each wit

HDU 1043 Eight數碼解題思路(bfs+hash IDA* 等)

中間 節點 sca 技巧 length div clu 鏈接 output 題目鏈接 https://vjudge.net/problem/HDU-1043 經典的八數碼問題,學過算法的老哥都會拿它練搜索 題意: 給出每行一組的數據,每組數據代表3*3的八數碼表,要求程序復

HDU1043-經典BFS+拓展開 數碼】 (待更)

給定一個序列,由1~8數字和字母x組成,表示的是一個3*3的矩形。每次操作x都能與相鄰的數字交換,問如何操作才能使得序列為{1,2,3,4,5,6,7,8,x}。   //多組資料-需要計算全部路徑後直接輸出 //反向搜尋+打表(離線) #include<iostream&

【基礎練習】【BFS+A*】codevs1225數碼難題題解

一點 說明 優先 data- push 練習 bool csdn tarjan 題目描寫敘述 Description Yours和zero在研究A*啟示式算法.拿到一道經典的A*問題,可是他們不會做,請你幫他們. 問題描寫敘述 在3×3的棋

數碼問題--bfs

mes als bsp lin dir str2 amt i++ pac 1 #include<iostream> 2 #include<cstring> 3 #define max 1000000 4 using namespace st

bzoj 1098 [POI2007]辦公樓biu bfs+補圖+雙向

solved 必須 ++ ont 一行 ast color cst code [POI2007]辦公樓biu Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1543 Solved: 743[Submit][Statu

Prime Path (+BFS) POJ-3126

The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit

Eight HDU - 1043 數碼問題 展開 + 反向 bfs +記錄路徑

bfs 剪枝要點 visit陣列 hash函式(康託展開) 記憶化 bfs 打表儲存所有可達路徑 優先佇列 periority queue 多點同時bfs 反向bfs + bfs 打表儲存所有路徑 stl + 正向bfs

哈爾濱理工大學軟體與微電子學院第屆程式設計競賽同步賽(高年級) G 小樂樂遊戲 【BFS

傳送門:https://ac.nowcoder.com/acm/contest/301/G   題意概括: 給一個地圖,有一個火山口 F 一個 起點 S 一個出口 E。 連結:https://ac.nowcoder.com/acm/contest/301/G來源:牛客網  

hdu1043 雙向bfs+拓展開【經典】

題意大致就是給你一個3X3的矩陣,你要把矩陣轉換成12345678的形式,在矩陣中是有一個空缺處可以供你移動滑塊的,問你是否可以把給你的矩陣轉換成12345678的形式,算了題意自己去看吧,有圖更加直接 思路:這裡主要考慮這幾個方面:第一個如何判斷經過一定轉換的矩陣是規範矩陣?這裡就用到了康

*【牛客 - 301哈爾濱理工大學軟體與微電子學院第屆程式設計競賽同步賽(高年級)】小樂樂遊戲(bfs,雙元bfs,思維)

題幹:   小樂樂覺得學習太簡單了,剩下那麼多的時間好無聊,於是便想打遊戲。         最近新出了一個特別火的遊戲,叫吃豬,小樂樂準備玩一玩。         吃豬遊戲很簡單,給定一個地圖,大小為

2612 bfs

打表預處理會降低複雜度,如果每次找一個'@'都跑一次bfs的話會超時; #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #

哈理工第屆程式設計競賽同步賽(高年級) G-小樂樂遊戲 (bfs,挑題的後果)

題目連結:哆啦A夢傳送門 剛看到這道題,一看是走迷宮類的題,看到就沒興趣,最不喜歡做的就是這些用bfs,dfs做的題,所以很顯然比賽時我想都不想,想著不要這題也罷,賽後才知道這題是有多水,嘔吐,從這次總結了一次教訓,以後打比賽,不要挑題做,不然會很吃虧,還是好好敲遍bfs好了,當練手了,最不