zoukankan      html  css  js  c++  java
  • 洛谷1242 新汉诺塔

    原题链接

    显然要先把较大的盘放到目标位置。
    有一个很明显的贪心方案:
    设当前要把第(x)大的盘子从(A)移到(B),则先把比(x)小的盘子全部移到(C)柱,再将第(x)大的盘子移到(B)柱,这样递归求解。
    该种贪心方案在大多数情况都是最优的,但是有个大佬出了一个(HACK)数据,将该贪心方案(HACK)掉了。
    以下是该数据

    //输入
    3
    1 3
    0
    2 2 1
    2 2 1
    0
    1 3
    //正确输出
    move 3 from A to B
    move 1 from C to B
    move 2 from C to A
    move 1 from B to A
    move 3 from B to C
    5
    //该贪心方案的错误输出
    move 1 from C to A
    move 2 from C to B
    move 1 from A to B
    move 3 from A to C
    move 1 from B to C
    move 2 from B to A
    move 1 from C to A
    7
    

    这时,我们就需要考虑另一种可能为最优的方案:
    设当前要把第(x)大的盘子从(A)移到(B),则先把比(x)小的盘子全部移到(B)上,再将(x)盘移到(C)柱,再将比(x)小的盘子全部移到(A)上,最后将(x)盘移到(B)上。
    虽然在大多数情况都是第一种更优,但是当比(x)小的盘子已经全部在(x)盘的目标柱上,这时可能是第二种方案更优。
    由于该种特殊情况只可能出现在第一步(因为第一步已经将比最大盘小的盘都移到一根柱上了),所以我们可以复制一遍数组,用第二种方案跑第一步,再用第一种方案接着跑,最后和全部用第一种方案取最小值输出即可。
    这题使用递归来写会更简洁一点(不过我复制一遍函数、数组名显得很长很臭)。

    #include<cstdio>
    using namespace std;
    const int N = 50;
    struct dd{
    	int x;
    	char f, t;
    };
    dd an[N << 10], b_an[N << 10];
    int a[N], b[N], b_a[N], b_b[N], s, b_s, k, b_k;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    void dfs(int x ,int y)
    {
    	if (!(a[x] ^ y))
    		return;
    	for (int i = x - 1; i; i--)
    		dfs(i, 6 - a[x] - y);
    	an[++k].x = x;
    	an[k].f = a[x] + 'A' - 1;
    	an[k].t = y + 'A' - 1;
    	a[x] = y;
    	s++;
    }
    void b_dfs(int x ,int y)
    {
    	if (!(b_a[x] ^ y))
    		return;
    	for (int i = x - 1; i; i--)
    		b_dfs(i, 6 - b_a[x] - y);
    	b_an[++b_k].x = x;
    	b_an[b_k].f = b_a[x] + 'A' - 1;
    	b_an[b_k].t = y + 'A' - 1;
    	b_a[x] = y;
    	b_s++;
    }
    void pr(int o, dd ans[])
    {
    	for (int i = 1; i <= o; i++)
    		printf("move %d from %c to %c
    ", ans[i].x, ans[i].f, ans[i].t);
    }
    int main()
    {
    	int i, j, n, m, x;
    	n = re();
    	for (i = 1; i < 4; i++)
    		for (m = re(), j = 1; j <= m; j++)
    		{
    			x = re();
    			a[x] = b_a[x] = i;
    		}
    	for (i = 1; i < 4; i++)
    		for (m = re(), j = 1; j <= m; j++)
    		{
    			x = re();
    			b[x] = b_b[x] = i;
    		}
    	for (i = n - 1; i; i--)//模拟用第二种方案跑第一步
    		b_dfs(i, b_b[n]);
    	x = b_a[n];
    	b_dfs(n, 6 - b_a[n] - b_b[n]);
    	for (i = n - 1; i; i--)
    		b_dfs(i, x);
    	b_dfs(n, b_b[n]);
    	for (i = n - 1; i; i--)//接着全部用第一种方案
    		b_dfs(i, b_b[i]);
    	for (i = n; i; i--)//全部用第一种方案跑
    		dfs(i, b[i]);
    	pr(s > b_s ? b_k : k, s > b_s ? b_an : an);
    	printf("%d", s > b_s ? b_s : s);
    	return 0;
    }
    
  • 相关阅读:
    Oracle数据库测试和优化最佳实践: OTest介绍 (转)
    Oracle数据库中心双活之道:ASM vs VPLEX (转)
    awrcrt更新到2.1(重大更新)
    Oracle性能图表工具:awrcrt.sql 介绍,更新到了2.14 (2018年3月31日更新)
    java虚拟机---内存
    如何进行高效的学习
    OpenGL绘制自由落体小球
    MDA系统分析实战--图书馆管理系统
    Python爬虫实战---抓取图书馆借阅信息
    Python--urllib3库详解1
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9818545.html
Copyright © 2011-2022 走看看