zoukankan      html  css  js  c++  java
  • hihocoder 1233 Boxes

    题意:类汉诺塔的一个东西……移动规则与汉诺塔一样,但初始状态为题目中给出的每根棍上一个盘子,目标状态为盘子在棍上按大小顺序排列,盘子只能在相邻的棍儿上移动。

    解法:广搜并打表记录从目标状态到所有可能的初始状态的答案。我记录每个盘子的位置为状态,vis用七位数组(被队友吐槽还真敢写啊=3=),然后每次转移状态的时候转化为每个棍儿上最小的盘子是啥(反正很抽象又不好解释……我懂就好啦哈哈哈哈哈哈哈哈哈哈(被队友嘲笑自暴自弃中))。答案的记录用转化为排列序数的方式。

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define LL long long
    using namespace std;
    int ans[8][6000];
    int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
    int order(int v[], int len)//将排列转化为排列序数
    {
        int i, j, temp, num;
        num = 0;
        for(i = 0; i < len - 1; i++)
        {
            temp = 0;
            for(j = i + 1; j < len; j++)
            {
                if(v[j] < v[i])
                    temp++;
            }
            num += fac[v[i] - 1] * temp;
        }
        return num;
    }
    struct node
    {
        int a[10], step;//a数组表示每个盘子放的棍儿的序号
        node(int tmp[], int tstep)
        {
            step = tstep;
            memcpy(a, tmp, sizeof a);
        }
        node() {}
    };
    bool vis[8][8][8][8][8][8][8];//记录状态
    queue <node> q;
    bool isanswer(int a[], int n)
    {
        int stick[8] = {0, 100, 100, 100, 100, 100, 100, 100};
        for(int i = 0; i < n; i++)
            stick[a[i]] = min(stick[a[i]], i + 1);
        for(int i = 1; i <= n; i++)
            if(stick[i] == 100) return false;
        return true;
    }
    void bfs(int a[], int n)
    {
        while(!q.empty()) q.pop();
        memset(vis, 0, sizeof vis);
        q.push(node(a, 0));
        vis[a[0]][a[1]][a[2]][a[3]][a[4]][a[5]][a[6]] = 1;
        while(!q.empty())
        {
            node tmp = q.front();
            q.pop();
            if(isanswer(tmp.a, n))
            {
                ans[n][order(tmp.a, n)] = tmp.step;
            }
            int stick[8] = {0, 100, 100, 100, 100, 100, 100, 100};
            for(int i = 0; i < n; i++)
                stick[tmp.a[i]] = min(stick[tmp.a[i]], i + 1);//算一下每根棍儿上最小的盘子是啥
            for(int i = 1; i <= n; i++)
            {
                if(stick[i] == 100) continue;
                if(i > 1 && (stick[i] < stick[i - 1] || (stick[i] != 100 && stick[i - 1] == 100)))//如果左面有棍儿且棍儿上最小的盘子比当前盘子大或者左面棍儿上没有盘子就转移状态
                {
                    tmp.a[stick[i] - 1] = i - 1;
                    if(!vis[tmp.a[0]][tmp.a[1]][tmp.a[2]][tmp.a[3]][tmp.a[4]][tmp.a[5]][tmp.a[6]])
                    {
                        vis[tmp.a[0]][tmp.a[1]][tmp.a[2]][tmp.a[3]][tmp.a[4]][tmp.a[5]][tmp.a[6]] = 1;
                        q.push(node(tmp.a, tmp.step + 1));
                    }
                    tmp.a[stick[i] - 1] = i;
                }
                if(i < n && (stick[i] < stick[i + 1] || (stick[i] != 100 && stick[i + 1] == 100)))//同上
                {
                    tmp.a[stick[i] - 1] = i + 1;
                    if(!vis[tmp.a[0]][tmp.a[1]][tmp.a[2]][tmp.a[3]][tmp.a[4]][tmp.a[5]][tmp.a[6]])
                    {
                        vis[tmp.a[0]][tmp.a[1]][tmp.a[2]][tmp.a[3]][tmp.a[4]][tmp.a[5]][tmp.a[6]] = 1;
                        q.push(node(tmp.a, tmp.step + 1));
                    }
                    tmp.a[stick[i] - 1] = i;
                }
            }
        }
    }
    void init()
    {
        memset(ans, -1, sizeof ans);
        int a[] = {1, 2, 3, 4, 5, 6, 7};
        for(int i = 1; i < 8; i++)
            bfs(a, i);
    }
    int main()
    {
        init();
        int T;
        scanf("%d", &T);
        while(T--)
        {
            int n, a[10], input[10];
            scanf("%d", &n);
            for(int i = 0; i < n; i++)
                scanf("%d", &input[i]);
            map <int, int> m;
            for(int i = 0; i < n; i++)
                m[input[i]] = i + 1;
            map <int, int> :: iterator ite = m.begin();
            for(int i = 0; ite != m.end(); ite++, i++) a[i] = ite -> second;
            int tmp = order(a, n);
            if(~ans[n][tmp])
                printf("%d
    ", ans[n][tmp]);
            else
                printf("-1
    ");
        }
        return 0;
    }
    

      

  • 相关阅读:
    web前端学习笔记(CSS盒子的定位)
    web前端学习笔记(CSS盒子的浮动)
    数百篇「原创」文章,助你完成技术「体系化」
    linux quota磁盘限额,引发的rename系统调用 errno:18
    dnsperf
    stop容器,把信号量传给java进程,优雅退出
    JNA 调用操作系统函数 和 系统调用
    自顶向下深入分析Netty(五)--Future
    来测试下你的Java编程能力
    Netty笔记
  • 原文地址:https://www.cnblogs.com/Apro/p/4826606.html
Copyright © 2011-2022 走看看