码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-10-16 01:39:58      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:最小   names   span   链接   inpu   www.   gif   问题   路径   

题目链接:传送门

题目大意:

汉诺塔,给定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\n", 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 += "\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);
    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

 

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

标签:最小   names   span   链接   inpu   www.   gif   问题   路径   

原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9795411.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!