1. 程式人生 > >hdu 1043 反向bfs標號+dfs查詢+stl+狀態壓縮

hdu 1043 反向bfs標號+dfs查詢+stl+狀態壓縮

因為9!=362880,所以我們可以通過寬搜從目標找到所有可達的情況,然後利用stl中的mp標記出,最後可以log(n)的查詢,屬於先打表後查詢,用十進位制數標記狀態

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <map>
#include <queue>
#define MAX 13
#define N 700007

using namespace std;

typedef long long LL;

map<LL,int> mark;

LL pos[MAX];
LL state;
LL goal;
int num[MAX];
bool flag;

void init ( )
{
    pos[0] = 1;
    for ( int i = 1 ; i <= 10 ; i++ )
        pos[i] = pos[i-1]*10;
    goal = 0;
    for ( int i = 0 ; i < 8 ; i++ )
        goal += pos[i]*(i+1);
}


struct Node
{
    int x,t,pre,id;
    char op;
    LL s;
}node[N];
int id = 1;


void set ( int a , int b , int c , LL d , char op )
{
    node[id].x = a;
    node[id].t = b;
    node[id].pre = c;
    node[id].s = d;
    node[id].op = op;
    node[id].id = id;
}

bool bfs ( )
{
    queue<Node> q;
    mark.clear();
    set ( 8 , 0 , -1 , goal , 0 );
    mark[goal] = 1;
    q.push ( node[id++] );
    while ( !q.empty( ) )
    {
        Node old = q.front();
       // cout << old.s << endl;
        int x = old.x;
        for ( int i = 0 ; i < 9 ; i++ )
            num[i] = (old.s/pos[i])%10;
        q.pop ( );
        if ( x-3 >= 0 )
        {
            LL s = old.s + num[x-3]*pos[x] + num[x]*pos[x-3]
                         - num[x-3]*pos[x-3] - num[x]*pos[x];
            if ( !mark[s] )
            {
                mark[s] = id;
                set ( x-3 , old.t+1 , old.id , s , 'd' );
                q.push ( node[id++] );
            }
        }
        if ( x+3 < 9 )
        {
            LL s = old.s + num[x+3]*pos[x] + num[x]*pos[x+3]
                         - num[x+3]*pos[x+3] - num[x]*pos[x];
            if ( !mark[s] )
            {
                mark[s] = id;
                set ( x+3 , old.t+1 , old.id , s , 'u' );
                q.push ( node[id++] );
            }
        }
        if ( (x-1)/3 == x/3 )
        {
            LL s = old.s + num[x-1]*pos[x] + num[x]*pos[x-1]
                         - num[x-1]*pos[x-1] - num[x]*pos[x];
            if ( !mark[s] )
            {
                mark[s] = id;
                set ( x-1 , old.t+1 , old.id , s , 'r' );
                q.push ( node[id++] );
            }
        }
        if ( (x+1)/3 == x/3 )
        {
            LL s = old.s + num[x+1]*pos[x] + num[x]*pos[x+1]
                         - num[x+1]*pos[x+1] - num[x]*pos[x];
            if ( !mark[s] )
            {
                mark[s] = id;
                set ( x+1 , old.t+1 , old.id , s , 'l' );
                q.push ( node[id++] );
            }
        }
    }
}


void dfs ( int id )
{
    if ( node[id].pre == -1 ) return;
    printf ( "%c" , node[id].op );
    dfs ( node[id].pre );
}

int main ( )
{
   // cout << 9*8*7*6*5*4*3*2*1<<endl;
    init ( );
    bfs( );
   //cout << "dasdasdasdas" << endl;
    char str[5];
    while ( ~scanf ( "%s" , str ) )
    {
        if ( str[0] != 'x' ) state = str[0] -48;
        else state = 0;
        for ( int i = 1 ; i < 9 ; i++ )
        {
            scanf ( "%s" , str );
            if ( str[0]!= 'x' ) state += ( str[0] - 48 )*pos[i];
        }
        // cout << goal << endl;
        // cout << state << endl;
        //int id = mark[state];
        //dfs ( id )
        int id = mark[state];
        if ( state == goal ) puts ( "" );
        else if ( id ) 
        {
            dfs ( id );
            puts ( "" );
        }
        else puts ( "unsolvable" );
    }
}