704 - Colour Hash 解题报告

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=645

一道非常好的bfs的题,不同于树,它是隐式图,可能会回到之前的状态,所以需要用hash表保存每一步的状态,重点是双向bfs,对于超过10步的bfs,搜索空间会非常大,必须使用双向bfs,保存终止状态回走8步,起始状态走8步即可,代码如下:

#include
#include
#include
#include

using namespace std;

#define MOD 99997

int f[] = {0,3,4,3,0,5,6,5,0,1,2,1,0,7,8,7,0,9,10,9,0,1,2,1};

void operation(int n, int *arr)
{
    int a1, a2;
    switch(n)
    {
        case 0:   //Left Wheel Clockwise rotation
            a1 = arr[10];
            a2 = arr[11];
            for(int i = 11; i > 1; --i)
            {
                arr[i] = arr[i-2];    
            }
            arr[0] = a1;
            arr[1] = a2;
            for(int i = 23; i > 20; --i)
                arr[i] = arr[i-12];
            break;
        case 1:    //Right Wheel Clockwise rotation
            a1 = arr[12];
            a2 = arr[13];
            for(int i = 12; i < 24; ++i)
                arr[i] = arr[i+2];
            arr[22] = a1;
            arr[23] = a2;
            for(int i = 11; i > 8; --i)
                arr[i] = arr[i+12];
            break;
        case 2:        //Left Wheel Counter-Clockwise rotation
            a1 = arr[0];
            a2 = arr[1];
            for(int i = 0; i < 12; ++i)
                arr[i] = arr[i+2];
            arr[10] = a1;
            arr[11] = a2;
            for(int i = 23; i > 20; --i)
                arr[i] = arr[i-12];
            break;
        case 3:        //Right Wheel Counter-Clockwise rotation
            a1 = arr[22];
            a2 = arr[23];
            for(int i = 23; i > 13; --i)
                arr[i] = arr[i-2];
            arr[12] = a1;
            arr[13] = a2;
            for(int i = 11; i > 8; --i)
                arr[i] = arr[i+12];
            break;
            
            
    }
}


typedef struct State State;
struct State{
    int arr[24];
    int step;
    string str;
    bool operator == (const State &s)
    {
        for(int i = 0; i < 24; ++i)
            if(arr[i] != s.arr[i])
                return false;
        return true;
    }
};

vector v[MOD];
vector fv[MOD];
queue q;
queue qf;
bool flag;
State final;

int getBucket(State &s)
{
    int hash = 1;
    for(int i = 0; i < 24; ++i)
    {
        hash = s.arr[i] + hash*33;
        hash = hash % MOD;
    }
    return hash;
}

bool exist(State &s, int which, State **n = NULL)
{
    int bucket = getBucket(s);
    if(which == 0) // v
    {
        int len = v[bucket].size();
        for(int i = 0; i < len; ++i)
            if(v[bucket][i] == s)
                return true;
        v[bucket].push_back(s);
        return false;
    }
    else if(which == 1) //fv
    {
        int len = fv[bucket].size();
        for(int i = 0; i < len; ++i)
            if(fv[bucket][i] == s)
            {
                if(n != NULL)
                    *n = &fv[bucket][i];
                return true;
            }
        return false;
    }
}

void insert(State &s)
{
    int bucket = getBucket(s);
    fv[bucket].push_back(s);
}

void bfs()
{
    while(!q.empty())
    {
        State n = q.front();
        q.pop();

        for(int i = 0; i < 4; ++i)
        {
            State tmp = n;
            State *tmpn;
            operation(i, tmp.arr);
            tmp.str += i+1 + '0';
            tmp.step += 1;

            if(tmp.step > 8)
                break;
            if(final == tmp)
            {
                flag = true;
                final = tmp;
                return ;
            }
            if(exist(tmp, 1, &tmpn))
            {
                flag = true;
                tmp.str += (*tmpn).str;
                tmp.step += (*tmpn).step;
                final = tmp;
                return;
            }
            if(!exist(tmp, 0))
                q.push(tmp);
        }
    }
}

void init(State &final)
{
    qf.push(final);
    while(!qf.empty())
    {
        State n = qf.front();
        qf.pop();
        for(int i = 3; i >= 0; --i)
        {       
            State tmp = n;
            operation(i, tmp.arr);
            string str = "";
            str += (i+2)%4 + 1 + '0';
            tmp.str = str + tmp.str;
            tmp.step += 1;
            if(tmp.step > 8)
                break;  
            if(!exist(tmp, 1))
            {       
                insert(tmp);
                qf.push(tmp);
            }       
        }
    }
}

int main()
{
    int T;
    cin>>T;
    for(int i = 0; i < 24; ++i)
        final.arr[i] = f[i];
    final.step = 0;
    final.str = "";
    init(final);
    while(T--)
    {
        for(int i = 0; i < 24; ++i)
            final.arr[i] = f[i];
        final.step = 0;
        final.str = "";
        State start;
        for(int i = 0; i < 24; ++i)
        {
            cin>>start.arr[i];
        }
        start.step = 0;
        start.str = "";
        
        flag = false;
        while(!q.empty())
            q.pop();
        for(int i = 0; i < MOD; ++i)
        {
            v[i].clear();
        }

        if(start == final)
        {
            cout<<"PUZZLE ALREADY SOLVED"<             continue;
        }
        State *tmp;
        if(exist(start, 1, &tmp))
        {
            flag = true;
            final = *tmp;
        }
        else
        {
            q.push(start);
            bfs();
        }
        if(flag)
            cout<         else
            cout<<"NO SOLUTION WAS FOUND IN 16 STEPS"<     }
    return 0;
}


测试case:

4

0 3 4 3 0 5 6 5 0 1 0 7 8 7 0 9 10 9 0 1 2 1 0 7
0 3 4 3 0 5 6 5 0 1 2 1 0 7 8 7 0 9 10 9 0 1 2 1
0 3 4 5 0 3 6 5 0 1 2 1 0 7 8 7 0 9 10 9 0 1 2 1
0 9 4 3 0 5 6 5 0 1 2 1 0 7 8 7 0 9 10 3 0 1 2 1

输出:

4

PUZZLE ALREADY SOLVED

1434332334332323

NO SOLUTION WAS FOUND IN 16 STEPS


注意起始状态要先搜寻一遍是否已经在倒回的8步状态中了,否则会出现134这样的结果

你可能感兴趣的:(算法)