• P1242 新汉诺塔(搜索+模拟退火)


    题目链接:传送门

    题目大意:

    汉诺塔,给定n个盘子(n <= 45),起始状态和结束状态,求最小的步数以及路径。

    思路:

    考虑用dfs贪心地将剩余最大盘归位。

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX_N = 50;
    const int SUM = 3;
    
    int N, ans;
    int f1[MAX_N], f2[MAX_N];
    
    void dfs(int cur, int st, int ed, bool now)
    {
        int mid = SUM - st - ed;
        if (st == ed) {
            if (cur > 1)
                dfs(cur-1, f1[cur-1], now ? f2[cur-1] : ed, now);
            return;
        }
        if (cur > 1)
            dfs(cur-1, f1[cur-1], mid, false);
        ans++;
        printf("move %d from %c to %c
    ", cur, 'A' + st, 'A' + ed);
        f1[cur] = ed;
        if (cur > 1)
            dfs(cur-1, f1[cur-1], now ? f2[cur-1] : ed, now);
    }
    
    void input()
    {
        ans = 0;
        cin >> N;
        for (int i = 0; i < 6; i++) {
            int x;
            cin >> x;
            while (x--) {
                int cur;
                cin >> cur;
                if (i/3)
                    f2[cur] = i%3;
                else
                    f1[cur] = i%3;
            }
        }
    }
    
    int main(){
        input();
        dfs(N, f1[N], f2[N], true);
        cout << ans << endl;
        return 0;
    }
    View Code

    以上代码会被这组数据hack。

    /*
    3
    1 3
    0
    2 2 1
    2 2 1
    0
    1 3
    */
    View Code

    但是大多数情况下贪心思路没有问题,所以用模拟退火优化。

    #include<bits/stdc++.h>
    
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int MAX_N = 50;
    const int SUM = 3;
    
    int N, ans, icur;
    string sans, scur;
    int ff1[MAX_N], ff2[MAX_N];
    int f1[MAX_N], f2[MAX_N];
    
    void mov(int cur, int st, int ed)
    {
        icur++;
        scur += "move ";
        if (cur >= 10)
            scur += char(cur/10 + '0');
        scur += char(cur%10 + '0');
        scur += " from ";
        scur += char(st + 'A');
        scur += " to ";
        scur += char(ed + 'A');
        scur += "
    ";
    }
    
    void dfs(int cur, int st, int ed, bool now)
    {
        int mid = SUM - st - ed;
        if (st == ed) {
            if (cur > 1)
                dfs(cur-1, f1[cur-1], now ? f2[cur-1] : ed, now);
            return;
        }
        if (cur > 1)
            dfs(cur-1, f1[cur-1], mid, false);
        mov(cur, st, ed);
        f1[cur] = ed;
        if (cur > 1)
            dfs(cur-1, f1[cur-1], now ? f2[cur-1] : ed, now);
    }
    
    void input()
    {
        ans = INF;
        cin >> N;
        for (int i = 0; i < 6; i++) {
            int x;
            cin >> x;
            while (x--) {
                int cur;
                cin >> cur;
                if (i/3)
                    ff2[cur] = i%3;
                else
                    ff1[cur] = i%3;
            }
        }
    }
    
    int main(){
        input();
        int T = 100;
        srand(44356542);
        while (T--) {
            icur = 0;
            scur = "";
            for (int i = 1; i <= N; i++) {
                f1[i] = ff1[i];
                f2[i] = ff2[i];
            }
            for (int i = N; i >= 1; i--) {
                if (rand()%(i+1) != 0)
                    dfs(i, f1[i], f2[i], true);
                else
                    dfs(i, f1[i], SUM-f1[i]-f2[i], true);
            }
            dfs(N, f1[N], f2[N], true);
            if (ans > icur) {
                ans = icur;
                sans = scur;
            }
        }
        cout << sans << ans << endl;
        return 0;
    }
    /*
    3
    1 3
    0
    2 2 1
    2 2 1
    0
    1 3
    */
    View Code
  • 相关阅读:
    剪绳子
    一步一步创建聊天程序2-利用epoll来创建简单的聊天室
    一步一步创建聊天程序1-利用进程和共享内存来创建简易聊天程序
    重写二路归并排序
    数据结构中的参见排序算法的实现,以及时间复杂度和稳定性的分析(2)
    数据结构中的参见排序算法的实现,以及时间复杂度和稳定性的分析(1)
    fork函数的一些小结
    LRU的实现(使用list)
    关于一道fork生成子进程的题目
    【转载】C++编译过程
  • 原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9795411.html
Copyright © 2020-2023  润新知