• long 龙


    Description

    汉诺塔升级了:现在我们有 (N) 个圆盘和 (N) 个柱子,每个圆盘大小都不一样,大的圆盘不能放在小的圆盘上面,(N) 个柱子从左到右排成一排。每次你可以将一个柱子上的最上面的圆盘移动到右边或左边的柱子上(如果移动之后是合法的话)。先在告述你初始时的状态,你希望用最少的步数将第 (i) 大的盘子移动到第 (i) 根柱子上,问最小步数。

    Input

    第一行一个正整数 (T) ,代表询问的组数。

    接下来 (T) 组数据,每组数据第一行一个整数 (N)

    接下来一行每行 (N) 个正整数,代表每个柱子上圆盘的大小。

    Output

    输出共 (T) 行,代表每次的答案。如果方案不存在,输出 (-1)

    Sample

    Sample Input

    4
    3
    2 1 3
    2
    7 8
    2
    10000 1000
    3
    97 96 95
    

    Sample Output

    4
    0
    -1
    20
    

    Limit

    对于 (70\%) 的数据, (N) 的值都是相等的。

    对于 (100\%) 的数据, (1le Tle 6 imes 10^3,1le Nle 7)

    Solution

    因为 (N) 很小,所以可以通过bfs状压 (mathrm{dp}) 把每种情况预处理出来,直接查询。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define rep(i, a, b) for (int i = a; i <= b; i++)
    
    inline int read() {
    	int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
    	while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
    }
    
    struct data{ int v, id; }a[10]; int b[10], c[10];
    bool cmp(const data& x, const data& y) { return x.v < y.v; }
    int ans[8000000], m[10] = { 1 }, p[10], top[10];
    bool tag[8000000];
    queue<int> q;
    
    void insert(int s) {
    	int len = 0, tmp = s; while(tmp) p[++len] = tmp % 10, tmp /= 10; reverse(p + 1, p + 1 + len);
    	memset(top, 0, sizeof top); for (int i = len; i; i--) top[p[i]] = i;
    	rep(i, 1, len) if(i == top[p[i]]) {
    		if(p[i] != 1 && (top[p[i] - 1] > i || !top[p[i] - 1])) {
    			int t = s - m[len - i]; if(!tag[t]) ans[t] = ans[s] + 1, q.push(t), tag[t] = 1;
    		}
    		if(p[i] != len && (top[p[i] + 1] > i || !top[p[i] + 1])) {
    			int t = s + m[len - i]; if(!tag[t]) ans[t] = ans[s] + 1, q.push(t), tag[t] = 1;
    		}
    	}
    }
    
    void init() {
    	int s = 0;
    	rep(i, 1, 7) m[i] = m[i - 1] * 10, s = s * 10 + i, q.push(s), tag[s] = 1;
    	while(!q.empty()) insert(q.front()), q.pop();
    }
    
    int main() {
    	freopen("long.in", "r", stdin); freopen("long.out", "w", stdout);
    	init();
    	int T; T = read();
    	while(T--) {
    		int n = read(), s = 0;
    		rep(i, 1, n) a[i].v = read(), a[i].id = i;
    		sort(a + 1, a + 1 + n, cmp);
    		rep(i, 1, n) b[a[i].id] = i;
    		rep(i, 1, n) c[b[i]] = i;
    		rep(i, 1, n) s = s * 10 + c[i];
    		printf("%d
    ", tag[s] ? ans[s] : -1);
    	}
    	return 0;
    }
    
  • 相关阅读:
    .linearDrag on rigidbody / rigidbody2D in code?
    Unity5权威讲解+项目源码+MP4
    C#的扩展方法解说
    use crunch compression
    IIS服务命令
    使用批处理打开控制面板中的功能
    一次性在一个文件夹里建立多个文件夹
    bat 批处理切换到当前脚本所在文件夹
    %date~0,4%和 %time~0,2%等用法详解(转)
    DOS批处理高级教程(还不错)(转)
  • 原文地址:https://www.cnblogs.com/aziint/p/8469510.html
Copyright © 2020-2023  润新知