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 } 
Uva10795

 

posted @ 2018-01-15 08:12  嘒彼小星  阅读(218)  评论(0编辑  收藏  举报