URAL_1806
这个题目思路比较明显,将边的关系找出来之后做最短路即可,但是由于N巨大,直接判断两个字符串能否转化是划不来的。
于是不妨将所有字符串放到哈希表中,然后对于当前字符串,枚举这个字符串改变一位、交换两位的情况,然后看能否在哈希表中找到变化之后的字符串,这样对于每个字符串至多枚举200种情况,复杂度还是可以接受的。
#include<stdio.h> #include<string.h> #define MAXD 50010 #define HASH 1000003 #define INF 0x3f3f3f3f int N, D, cost[15], head[HASH], next[MAXD]; char b[MAXD][15], code[15]; int dis[MAXD], pre[MAXD], tree[4 * MAXD]; int hash(char *str) { int i, h = 0, seed = 131; while(*str) h = h * seed + *(str ++); return (h & 0x7fffffff) % HASH; } void Insert(int s) { int h = hash(b[s]); next[s] = head[h]; head[h] = s; } int search(char *str) { int i, h = hash(str); for(i = head[h]; i != -1; i = next[i]) if(strcmp(b[i], str) == 0) break; return i; } void init() { int i; for(i = 0; i < 10; i ++) scanf("%d", &cost[i]); memset(head, -1, sizeof(head)); for(i = 1; i <= N; i ++) { scanf("%s", b[i]); Insert(i); } } void update(int i) { for(; i ^ 1; i >>= 1) tree[i >> 1] = dis[tree[i]] < dis[tree[i ^ 1]] ? tree[i] : tree[i ^ 1]; } void Swap(char &x, char &y) { char t; t = x, x = y, y = t; } void dfs(int cur, int n) { if(cur == 1) { printf("%d\n%d", n, cur); return ; } dfs(pre[cur], n + 1); printf(" %d", cur); } void solve() { int i, j, x, y; for(D = 1; D < N + 2; D <<= 1); memset(tree, 0, sizeof(tree)); memset(dis, 0x3f, sizeof(dis)); dis[1] = 0, pre[1] = 0, tree[D + 1] = 1, update(D + 1); while(x = tree[1]) { strcpy(code, b[x]); tree[D + x] = 0, update(D + x); for(i = 0; i < 10; i ++) for(j = '0'; j <= '9'; j ++) if(j != code[i]) { code[i] = j; y = search(code); if(y != -1 && dis[x] + cost[i] < dis[y]) dis[y] = dis[x] + cost[i], pre[y] = x, tree[D + y] = y, update(D + y); code[i] = b[x][i]; } for(i = 0; i < 10; i ++) for(j = i + 1; j < 10; j ++) if(code[i] != code[j]) { Swap(code[i], code[j]); y = search(code); if(y != -1 && dis[x] + cost[i] < dis[y]) dis[y] = dis[x] + cost[i], pre[y] = x, tree[D + y] = y, update(D + y); Swap(code[i], code[j]); } } if(dis[N] == INF) printf("-1\n"); else { printf("%d\n", dis[N]); dfs(N, 1); printf("\n"); } } int main() { while(scanf("%d", &N) == 1) { init(); solve(); } return 0; }