zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    设置root密码
    切分和组合图片(一)
    android 游戏开发libgdx(一)
    用SharePoint.OpenDocuments打开的文档如何控制它的ActiveWindow.View.ShowXMLMarkup(转)
    sp_helptext 命令
    CMMI 配置管理 简介(转)
    文本框中只能输入字符的正则表达式.
    基于CMM和CMMI的配置管理(转)
    正则表达式详述(转)
    选中多个CheckBox赋给文本框.
  • 原文地址:https://www.cnblogs.com/aziint/p/8469510.html
Copyright © 2011-2022 走看看