SPOJ 5151 Alice’s Cube

    一开始反应的是用状态压缩dp来做,后来一看步数很小,只有三步,于是直接暴力就可以了。另外由于测试数据比较多,可以先从最终状态BFS一遍,保留下所有结果,然后每次判断就是O(1)的了。

#include<stdio.h>
#include<string.h>
#define MAXD 20
#define MAXM 160
#define MAXS 100010
#define INF 0x3f3f3f3f
int first[MAXD], e, dis[MAXS], next[MAXM], v[MAXM];
int q[MAXS];
const int ini = (1 << 16) - (1 << 8);
void add(int x, int y)
{
    v[e] = y;
    next[e] = first[x], first[x] = e ++;    
}
void addedge()
{
    e = 0;
    memset(first, -1, sizeof(first));    
    add(1, 2), add(1, 3), add(1, 5), add(1, 9);
    add(2, 4), add(2, 6), add(2, 1), add(2, 10);
    add(3, 1), add(3, 4), add(3, 7), add(3, 11);
    add(4, 2), add(4, 3), add(4, 8), add(4, 12);
    add(5, 1), add(5, 6), add(5, 7), add(5, 13);
    add(6, 2), add(6, 5), add(6, 8), add(6, 14);
    add(7, 3), add(7, 5), add(7, 8), add(7, 15);
    add(8, 4), add(8, 7), add(8, 6), add(8, 16);
    add(9, 1), add(9, 10), add(9, 11), add(9, 13);
    add(10, 2), add(10, 9), add(10, 12), add(10, 14);
    add(11, 3), add(11, 9), add(11, 12), add(11, 15);
    add(12, 4), add(12, 10), add(12, 11), add(12, 16);
    add(13, 9), add(13, 5), add(13, 14), add(13, 15);
    add(14, 10), add(14, 13), add(14, 6), add(14, 16);
    add(15, 7), add(15, 11), add(15, 13), add(15, 16);
    add(16, 8), add(16, 12), add(16, 14), add(16, 15);
}
void prepare()
{
    int i, j, k, x, y, rear = 0;
    addedge();
    memset(dis, 0x3f, sizeof(dis));
    dis[ini] = 0, q[rear ++] = ini;
    for(i = 0; i < rear; i ++)
    {
        x = q[i];
        if(dis[x] >= 3)
            break;
        for(j = 1; j <= 16; j ++)
            for(k = first[j]; k != -1; k = next[k])
            {
                if((x & 1 << j - 1) != (x & 1 << v[k] - 1))
                {
                    y = x ^ (1 << j - 1) ^ (1 << v[k] - 1);
                    if(dis[y] == INF)
                    {
                        dis[y] = dis[x] + 1;
                        q[rear ++] = y;    
                    }    
                }
            }
    }
}
void solve()
{
    int i, j, k, a[20];
    for(i = 0; i < 16; i ++)
        scanf("%d", &a[i]);
    k = 0;
    for(i = 15; i >= 0; i --)
        k = k << 1 | a[i];
    if(dis[k] == INF)
        printf("more\n");
    else
        printf("%d\n", dis[k]);
}
int main()
{
    int t, tt;
    prepare();
    scanf("%d", &t);
    for(tt = 1; tt <= t; tt ++)
    {
        printf("Case #%d: ", tt);
        solve();    
    }
    return 0;    
}
原文地址:https://www.cnblogs.com/staginner/p/2599532.html