博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hihoCoder 1233 : Boxes(盒子)
阅读量:5225 次
发布时间:2019-06-14

本文共 4503 字,大约阅读时间需要 15 分钟。

hihoCoder #1233 : Boxes(盒子)

时间限制:1000ms
单点时限:1000ms
内存限制:256MB

Description - 题目描述

  There is a strange storehouse in PKU. In this storehouse there are n slots for boxes, forming a line. In each slot you can pile up any amount of boxes. The limitation is that you can only pile a smaller one above a bigger one, in order to keep balance. The slots are numbered from 1 to n. The leftmost one is slot 1.

 

  At first there is exactly one box in each slot. The volume of the box in slot i is vi. As a virgo, you decide to sort these boxes by moving some of them. In each move you can choose a slot and move the top box in this slot to an adjacent slot (of course you can only put it on the top). You should ensure that the limitation mentioned above is still satisfied after this move. After the sort operation, there should be exactly one box in each slot, and for each pair of adjacent slots, the box in the left one should be smaller than the box in the right one.

 

  Your task is to calculate the minimum number of moves you need to sort the boxes.

PKU里有个奇怪的仓库。仓库里有n个连成一线的盒子槽。每个槽上可以叠堆人员数量的盒子。为了保持平衡,唯一的限制是:只能把小盒子放在大盒子上面。槽的编号为从1到n。最左边的槽为1。开始时,每个槽都有一个盒子。槽i中盒子的体积为vi。作为处女座,你决定通过移动盒子来对其进行排序。每次移动时你都能选择一个槽,把顶部的盒子移动到相邻的槽(当然你还是只能放在顶部)。你需要确保移动后依然满足上述的限制。排序过后,每个槽都应有一个盒子,并且对于任意一对相邻的槽,左边的盒子要小于右边的盒子。你的任务就是计算完成盒子排序的最少移动次数。
CN

 

Input - 输入

  In the first line there’s an integer T(T≤6000), indicating the number of test cases. The following 2T lines describe the test cases.

 

  In each test case, the first line contains an integer n, indicating the number of slots. The second line contains n integers v1,v2…vn, indicating the volume of the boxes. It is guaranteed that all vi in a test case are different.

 

  Please note that n<8,0≤vi≤104

第一行有一个整数T,表示测试用例的数量。随后有2T行的测试用例。对于每组测试用例,第一行有一个整数n,表示槽的数量。第二行有n个整数 v1,v2 … vn,表示盒子的体积。保证一组用例中所有的vi都是不同的。请注意n<8,0≤vi≤10^4
CN

 

Output - 输出

  For each test case, print a line containing one integer indicating the answer. If it’s impossible to sort the boxes, print -1.

对于每组测试用例,输出一行整数答案。如果无法完成盒子排序,输出-1。
CN

 

Sample Input - 样例输入

432 1 327 8210000 1000397 96 95

 

Sample Output - 样例输出

40-120

 

题解

  开始时脑袋一抽冒了个2^(8*8)的状态表示,看到2^21后恍然大悟。 写完时没注意T,弄了个在线查询超时了……默默地改成打表

    压缩状态:

       [1--] [2--] [3--] [4--] [5--] [6--] [7--]

      最多7个数,把数字离散化成位置。

      用3位二进制标记第i小的数存放的位置,[0, 6]或[1, 7]的方式都差不多。 状态数2^(3*7)。

      (但是想了想为什么不把3位全用上,估计是因为2^(3*8)……)

 

    后面就是BFS打表,枚举所有情况。

 

后记:

打表刚刚写完的时候在本地的VS跑了2.5s的初始化,结果hihoCoder上居然A了?!哈?还只花了0.1s

吓得我以为hihoCoder用的是80GHz的CPU……

后面经过对比估计是VS和G++ STL的区别,VS不知道为什么这次queue特别低效。

经过稍微优化后也只能达到1.3s的初始化速度,G++基本为0.2s内初始化完成。

估计还是queue的锅,不知这速度差距是不是算得上BUG了。

 

代码 C++

1 #include 
2 #include
3 #include
4 #include
5 int n, ed, bit[8] = { 1 }, map[10005]; 6 unsigned int opt[2 << 21 | 1], data[8]; 7 std::queue
q; 8 9 int red(){10 int now, tmp[8], i;11 scanf("%d", &n);12 for (i = 0; i < n; ++i) scanf("%d", data + i);13 memcpy(tmp, data, sizeof data);14 std::sort(tmp, tmp + n);15 for (i = 0; i < n; ++i) map[tmp[i]] = i;16 for (i = now = 0; i < n; ++i) now ^= bit[map[data[i]]] * (i + 1);17 return now;18 }19 20 void setData(int d){21 int i, j;22 memset(data, -1, sizeof data);23 for (i = 1; i <= n; ++i, d >>= 3){24 if (~data[j = (d & 7) - 1]) continue;25 data[j] = i;26 }27 }28 void BFS(){29 int now, nxt, i;30 while (!q.empty()){31 setData(now = q.front()); q.pop();32 for (i = 0; i < n; ++i){33 if (data[i] == -1) continue;34 if (i < n - 1){35 if (data[i] < data[i + 1]){36 nxt = now + bit[data[i] - 1];37 if (opt[now] + 1 < opt[nxt]) opt[nxt] = opt[now] + 1, q.push(nxt);38 }39 }40 if (i > 0){41 if (data[i] < data[i - 1]){42 nxt = now - bit[data[i] - 1];43 if (opt[now] + 1 < opt[nxt]) opt[nxt] = opt[now] + 1, q.push(nxt);44 }45 }46 }47 }48 }49 void rdy(){50 memset(opt, -1, sizeof opt);51 int now, i;52 for (i = 1; i < 8; ++i) bit[i] = bit[i - 1] << 3;53 for (i = now = 0; i < 7; n = ++i, BFS()){54 q.push(now += bit[i] * (i + 1)); opt[now] = 0;55 }56 }57 58 int main(){59 rdy();60 int t;61 for (scanf("%d", &t); t--; printf("%d\n", opt[red()]));62 return 0;63 }

 

转载于:https://www.cnblogs.com/Simon-X/p/6371529.html

你可能感兴趣的文章
图像处理中双线性插值
查看>>
RobHess的SIFT代码解析之RANSAC
查看>>
03 线程池
查看>>
201771010125王瑜《面向对象程序设计(Java)》第十三周学习总结
查看>>
手机验证码执行流程
查看>>
python 基础 ----- 变量
查看>>
设计模式课程 设计模式精讲 2-2 UML类图讲解
查看>>
Silverlight 的菜单控件。(不是 Toolkit的)
查看>>
:hover 鼠标同时触发两个元素变化
查看>>
go语言学习十三 - 相等性
查看>>
Idea 提交代码到码云(提交到github也大同小异)
查看>>
c#连接excel2007未安装ISAM解决
查看>>
Mono 异步加载数据更新主线程
查看>>
初识lua
查看>>
我是插件狂人,jDuang,jValidator,jModal,jGallery
查看>>
张季跃 201771010139《面向对象程序设计(java)》第四周学习总结
查看>>
如何解除循环引用
查看>>
android中fragment的使用及与activity之间的通信
查看>>
字典【Tire 模板】
查看>>
jquery的contains方法
查看>>