bzoj1019: [SHOI2008]汉诺塔

来源:互联网 发布:开淘宝需要多少保证金 编辑:程序博客网 时间:2024/05/21 17:08

题面在这里

首先f[i][j]表示第i个柱子上j个盘,移到g[i][j]上需要的步数。g[i][j]保存上述状态下移到哪个柱子。

假设现在的状态是第x个柱子i个盘,设y = g[x][i-1],k = 3-x-y(k是剩下一个盘)

然后我们考虑操作:肯定是把x上的i-1个先移到y,剩下一个移到k,再移动y上的i-1个盘。

至于y上i-1个盘怎么移,需要分类讨论:

  • 如果g[y][i-1] = k,那么就直接把i-1个移到k就好了。g[x][i] = k。
  • 否则g[y][i-1] = x,那么先把y上的i-1个移到x,把k上的一个移到y,再把x上的i-1个移到y。g[x][i] = y。

f[x][i]也相应地能算出来了。


/*************************************************************Problem: bzoj 1019 [SHOI2008]汉诺塔User: fengyuanLanguage: C++Result: AcceptedTime: 0 msMemory: 824 kbSubmit_Time: 2017-11-16 20:03:13*************************************************************/#include<cstdio>#include<cstring>using namespace std;typedef long long LL;const int N = 35;int n;int g[5][N];LL f[5][N];char s[10][5];int main(){scanf("%d", &n);for (int i = 1; i <= 6; i ++){scanf("%s", s[i]);}for (int i = 6; i >= 1; i --){g[s[i][0] - 'A'][1] = s[i][1] - 'A';}for (int i = 0; i < 3; i ++){f[i][1] = 1;}for (int i = 2; i <= n; i ++)for (int x = 0; x < 3; x ++){int y = g[x][i-1], k = 3-x-y;if (g[y][i-1] == k){g[x][i] = k;f[x][i] = f[x][i-1] + 1 + f[y][i-1];} else {g[x][i] = y;f[x][i] = f[x][i-1] + 1 + f[y][i-1] + 1 + f[x][i-1];}}printf("%lld\n", f[0][n]);return 0;}


原创粉丝点击