ACM学习历程—Hihocoder 1233 Boxes(bfs)(2015北京网赛)
时间限制:1000ms
单点时限:1000ms
内存限制:256MB
描述
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.
输入
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
输出
For each test case, print a line containing one integer indicating the answer. If it’s impossible to sort the boxes, print -1.
样例输入
4
3
2 1 3
2
7 8
2
10000 1000
3
97 96 95
样例输出
4
0
-1
20
题目看起来跟汉诺塔很像,但是条件更苛刻。
不过由于n < 8,所以状态数最多是1!+2!+3!+…7!。
但是如果想模拟移动的过程,在移动过程中箱子会重叠,这样的话,所有状态的数目应该是1^1+2^2+3^3…7^7。
这个状态数目不是特别大。
而且对于1,12,123,1234,12345,123456,1234567这种状态的值都为0.
于是,就可以从这些为0的状态出发,去模拟箱子移动的过程,然后bfs求得所有状态的解。相当于一个倒推的过程。
首先肯定需要把所有数处理成连续的数,比如123456这样。这个处理方法有很多。
但是状态的存储是一个问题。
可以用一个结构体来存,那么里面会有一个长度为7的数组index[i],表示大小为i的箱子所在的位置。这样的话需要map来存结果,但是需要重载小于号。
用string存的话可以不用重载小于号,但是也需要map来保存结果。
但是这里map的效率是logn,经测时间很长。。
也就是说这个logn不能乘上去,虽然理论上计算复杂度应该够,但是实际上1S内无法处理。
也是说状态跟结果的映射关系需要在常数时间内完成。
由于状态最大是7777777,也就是说直接用十进制int来存状态的话是可以用一维数组来完成的。
网上也有用二进制状压的,每三位表示一个箱子的位置,这样最多21位就能表示所有箱子的状态,也就是2097152。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <string>
#define LL long long using namespace std; struct ARG
{
int val;
int id;
}arg[]; bool cmpARG(ARG x, ARG y)
{
return x.val < y.val;
} int n;
int s[];
int ans[]; void bfs(int cnt)
{
int k[], tmp, state, mi;
queue<int> q;
state = ;
for (int i = ; i <= cnt; ++i)
state = *state+i;
ans[state] = ;
q.push(state);
while (!q.empty())
{
state = q.front();
q.pop();
tmp = state;
for (int i = ; i < cnt; ++i)
{
k[cnt--i] = tmp%;
tmp /= ;
}
for (int i = ; i < cnt; ++i)
{
mi = -;
for (int j = ; j < i; ++j)
{
if (k[j] == k[i])
{
mi = j;
break;
}
}
if (mi != -)
continue;
if (k[i] > )
{
k[i]--;
mi = -;
for (int j = ; j < i; ++j)
{
if (k[j] == k[i])
{
mi = j;
break;
}
}
tmp = ;
for (int i = ; i < cnt; ++i)
tmp = *tmp+k[i];
if (ans[tmp] == - && mi == -)
{
ans[tmp] = ans[state]+;
q.push(tmp);
}
k[i]++;
}
if (k[i] < cnt)
{
k[i]++;
mi = -;
for (int j = ; j < i; ++j)
{
if (k[j] == k[i])
{
mi = j;
break;
}
}
tmp = ;
for (int i = ; i < cnt; ++i)
tmp = *tmp+k[i];
if (ans[tmp] == - && mi == -)
{
ans[tmp] = ans[state]+;
q.push(tmp);
}
k[i]--;
}
}
}
} void init()
{
memset(ans, -, sizeof(ans));
for (int i = ; i < ; ++i)
bfs(i);
} void input()
{
scanf("%d", &n);
for (int i = ; i < n; ++i)
{
scanf("%d", &arg[i].val);
arg[i].id = i;
}
sort(arg, arg+n, cmpARG);
for (int i = ; i < n; ++i)
s[i]=arg[i].id+;
} void work()
{
if (n == )
return;
int k = ;
for (int i = ; i < n; ++i)
k = *k+s[i];
printf("%d\n", ans[k]);
} int main()
{
//freopen("test.in", "r", stdin);
init();
int T;
scanf("%d", &T);
for (int i = ; i < T; ++i)
{
input();
work();
}
return ;
}
ACM学习历程—Hihocoder 1233 Boxes(bfs)(2015北京网赛)的更多相关文章
- ACM学习历程—Hihocoder 1139 二分·二分答案(bfs)
http://hihocoder.com/problemset/problem/1139 这题提示上写的是二分,但是感觉不二分应该也可以,至少题目是AC的... 二分的思想就是二分答案的值,看能不能在 ...
- ACM学习历程—Hihocoder 1291 Building in Sandbox(dfs && 离线 && 并查集)
http://hihocoder.com/problemset/problem/1291 前几天比较忙,这次来补一下微软笔试的最后一题,这题是这次微软笔试的第四题,过的人比较少,我当时在调试B题,没时 ...
- ACM学习历程—Hihocoder 1289 403 Forbidden(字典树 || (离线 && 排序 && 染色))
http://hihocoder.com/problemset/problem/1289 这题是这次微软笔试的第二题,过的人比第三题少一点,这题一眼看过去就是字符串匹配问题,应该可以使用字典树解决.不 ...
- ACM学习历程—Hihocoder 1290 Demo Day(动态规划)
http://hihocoder.com/problemset/problem/1290 这题是这次微软笔试的第三题,过的人比第一题少一点,这题一眼看过去就是动态规划,不过转移方程貌似不是很简单,调试 ...
- ACM学习历程—Hihocoder 1288 Font Size(暴力 || 二分)
http://hihocoder.com/problemset/problem/1288 这题是这次微软笔试的第一题,关键的是s的上限是min(w, h),这样s的范围只有到1000,这样就可以直接暴 ...
- ACM学习历程—Hihocoder [Offer收割]编程练习赛1
比赛链接:http://hihocoder.com/contest/hihointerview3/problem/1 大概有一个月没怎么打算法了.这一场的前一场BC,也打的不是很好.本来Div1的A和 ...
- ACM学习历程—Hihocoder 1164 随机斐波那契(数学递推)
时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 大家对斐波那契数列想必都很熟悉: a0 = 1, a1 = 1, ai = ai-1 + ai-2,(i > 1). ...
- ACM学习历程—Hihocoder 1178 计数(位运算 && set容器)(hihoCoder挑战赛12)
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Rowdark是一个邪恶的魔法师.在他阅读大巫术师Lich的传记时,他发现一类黑魔法来召唤远古生物,鱼丸. 魔法n能召 ...
- ACM学习历程—Hihocoder 1177 顺子(模拟 && 排序 && gcd)(hihoCoder挑战赛12)
时间限制:6000ms 单点时限:1000ms 内存限制:256MB 描述 你在赌场里玩梭哈,已经被发了4张牌,现在你想要知道发下一张牌后你得到顺子的概率是多少? 假定赌场使用的是一副牌,四种 ...
随机推荐
- 如何更好的利用Node.js的性能极限
通过使用非阻塞.事件驱动的I/O操作,Node.js为构建和运行大规模网络应用及服务提供了很好的平台,也受到了广泛的欢迎.其主要特性表现为能够处理庞大的并且高吞吐量的并发连接,从而构建高性能.高扩展性 ...
- centos7.0 activemq的安装
1:下载地址http://activemq.apache.org/activemq-590-release.html 2:wget http://archive.apache.org/dist/act ...
- TP框架的修改,删除
先把数据库的素具显示出来 public function xiugai() { $code= "n001";//修改的主键值 $n = M("nation"); ...
- ULN2003A 使用,有坑
8脚接24V负极 9脚接24V正极 16接24V继电器,再接到24V正极 1-7无论给5V 正 或 负,10-16都不能达到24V,越靠近输入端的输出端电压越大,最大的才11V,最小的2.5V 最后发 ...
- 洛谷P2661 信息传递==coedevs4511 信息传递 NOIP2015 day1 T2
P2661 信息传递 题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知 ...
- Spring @Configuration注解
1 该注解的用途 这个注解表示这个类可以作为spring ioc容器bean的来源,其本质上它是对xml文件中创建bean的一种替换.有了这个注释,Spring framework就能在需要的时候构造 ...
- 在普通网页中如何调用html5+的plus对象
<script> //用法: HTML5+的plus对象,必须由click事件触发后,才能在普通网页中使用.所以在没有click的情况下,调用本文件可以解决问题! //在代码中使用: pl ...
- 转。git 乌龟的使用安装
TortoiseGit 简称 tgit, 中文名海龟Git. 海龟Git只支持神器 Windows 系统, 有一个前辈海龟SVN, TortoiseSVN和TortoiseGit都是非常优秀的开源的版 ...
- PHP中ob系列函数讲解(浏览器缓存技术) (转)
Output Control 函数可以让你自由控制脚本中数据的输出.它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况. 输出控制函数不对使用 header() 或 setcooki ...
- Java之线程池(一)
在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统 ...