一开始反应的是用状态压缩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");elseprintf("%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/archive/2012/07/19/2599532.html