Uva10795 A Different Task
A Different Task
https://vjudge.net/problem/UVA-10795
题目大意:给定一个汉诺塔初末状态,求从初状态到末状态最少需要多少步。
考虑最大的一个初末不同盘子,设这个盘子为k,初始在start[k],终止在final[k]
比k大的盘子一定在正确位置且在最下面,可以忽略,不妨把他们去掉
k移动到final[k],final[k]上只能有一个盘子k,start[k]上没有盘子,那么1...k-1在6 - start[k] - final[k]上
设f(P,i,j)表示初始状态为P时,把1..i盘子移动到j上的最小步数。若P[i] = j,即i在j盘子上,那么f(P,i,j) = f(P,i-1,j)
若P[i]!=j,若把1...i移动到j,需要6 - P[i] - j做中转把1...i-1移动到(f(P,i-1,6-P[i]-j)),把k移动到j上(1),再把1..k-1以6 - P[i] - j为中转移动到j上
分别从初状态和末状态移动到标准状态即可
答案为f(start, k - 1, 6 - start[k] - final[k]), f(final, k - 1, 6 - start[k] - final[k])
被各种细节卡,比如longlong
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <cmath> 8 #include <vector> 9 #define min(a, b) ((a) < (b) ? (a) : (b)) 10 #define max(a, b) ((a) > (b) ? (a) : (b)) 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 12 inline void swap(long long &a, long long &b) 13 { 14 long long tmp = a;a = b;b = tmp; 15 } 16 inline void read(long long &x) 17 { 18 x = 0;char ch = getchar(), c = ch; 19 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 20 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 21 if(c == '-') x = -x; 22 } 23 24 const long long INF = 0x3f3f3f3f; 25 const long long MAXN = 60 + 5; 26 27 long long start[MAXN], final[MAXN]; 28 29 long long n; 30 31 long long dfs1(long long i, long long j) 32 { 33 if(i <= 0) return 0; 34 if(start[i] == j) return dfs1(i - 1, j); 35 return dfs1(i - 1, 6 - start[i] - j) + ((long long)1 << (i - 1)); 36 } 37 38 long long dfs2(long long i, long long j) 39 { 40 if(i <= 0) return 0; 41 if(final[i] == j) return dfs2(i - 1, j); 42 return dfs2(i - 1, 6 - final[i] - j) + ((long long)1 << (i - 1)); 43 } 44 45 long long t; 46 47 int main() 48 { 49 while(scanf("%d", &n) != EOF && n) 50 { 51 ++ t; 52 memset(start, 0, sizeof(start)); 53 memset(final, 0, sizeof(final)); 54 for(register long long i = 1;i <= n;++ i) read(start[i]); 55 for(register long long i = 1;i <= n;++ i) read(final[i]); 56 long long k = n; 57 while(start[k] == final[k] && k) --k; 58 if(k <= 0) printf("Case %lld: 0\n", t); 59 else printf("Case %lld: %lld\n", t, dfs1(k - 1, 6 - start[k] - final[k]) + dfs2(k - 1, 6 - start[k] - final[k]) + 1); 60 } 61 return 0; 62 }