1 条题解
-
0
自动搬运
来自洛谷,原作者为

封禁用户
None搬运于
2025-08-24 21:22:49,当前版本为作者最后更新于2018-06-15 18:50:32,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
这道题是建立在P4285 [SHOI2008]汉诺塔 之上的,如果没有做过,建议尝试一下。
这道题是建立在原版之上的,策略一样,也是要将盘子由初始柱经过中转柱转移至目标柱。
那么,这道题的升级在于它规定了初始与目标,还有就是---
它的各个柱子上可能都有盘子,而没有一个空柱子供你中转,这个问题等下会提到。
另外强调一下:当有大盘子要过时,小盘子统统得
滚开这也就是上面呢个问题的难之所在,只有等大的过了,小的才能上。所以只要确定中转柱,问题便迎刃而解了。
呢么怎么确定中转柱呢??
暴力枚举????O(∩_∩)O~ 呵呵,泽斯不可能的。
那怎么办?
=推理开始===
我们设first[x]是初始柱,last是目标柱
那么我将此时的初始柱标号以下的柱子统统转移到 6-(first[x]+y)的地方去
为什么呢??
仔细想想:6代表的是3根初始柱,3根目标柱
6-(first[x]+y) 便是我们的中转柱了,因为到这个位置是最优的。
你应该猜到了,这个操作就是把小盘子统统移开
接下来只要安心的输出,累加计数器就可以了。 皆大欢喜
=推理结束===
泽是鄙人的代码:
#include<cstdio> int n,last[55],first[55],ans=0,m,x; const char ch[]={'0','A','B','C'}; //char数组的第一位要有零占位,调了n久呀,一定要吸取教训。 void dfs(int x,int y) { if(first[x]==y) return; for(int i=x-1;i>=1;i--) dfs(i,6-(first[x]+y)); //处理小盘子。 printf("move %d from %c to %c\n",x,ch[first[x]],ch[y]); //输出。 first[x]=y;ans++; //类似于并查集,找完就将x,y合并,并且累加答案数。 } int main() { scanf("%d",&n); for(int i=1;i<=3;i++) { scanf("%d",&m); for(int j=1;j<=m;j++) scanf("%d",&x),first[x]=i; } for(int i=1;i<=3;i++) { scanf("%d",&m); for(int j=1;j<=m;j++) scanf("%d",&x),last[x]=i; } //将每一个目标与初始柱打上标记 for(int i=n;i>=1;i--) dfs(i,last[i]); //第i个要到目标柱那里去。 printf("%d",ans); return 0; }本题题解到此结束,谢谢大家。
- 1
信息
- ID
- 242
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者