HihoCoder 1233 Boxes (bfs 状压)
2017-10-07 17:26
351 查看
题意:有n个盒子放在n个放盒子的位置(1<=n<=7),每个盒子大小不一,每次可以将一个盒子往它相邻的位置移,但是只能把小的
盒子往没盒子的位置或大的盒子上移。求最小移动多少次后盒子能从小到大排列地放在每个位置(每个位置一个)(T<=6e3)
思路:因为n才7,所以容易想到状压。每个位置有3位二进制表示,所以一共需要2^21这么大的数组。状态表示第i个盒子所在的位
置。(因为盒子大小只与相对大小有关,所以一开始先将大小离散化成1-n)。因为T比较大,每次盒子只能向左放或者向右放,那
么我们从结束的位置开始搜索,bfs预处理出目标状态到所有状态所需要的最小步数,这样对于每个询问可以O(1)回答。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e6+5;
int vis[maxn];
bool book[15];
void bfs(int n)
{
queue<int> q;
int tmp = 0;
for(int i = 0; i < n; i++)
tmp += (i+1)*(1<<(3*i));
q.push(tmp);
vis[tmp] = 0;
while(!q.empty())
{
int u = q.front(); q.pop();
memset(book, 0, sizeof(book));
for(int i = 0; i < n; i++) //枚举第i+1个盒子,注意是从小的开始枚举
{
int pos = (u>>(i*3))%8;//第i+1个盒子所在位置
if(book[pos]) continue; //表示这个盒子上有比它小的盒子,所以不能移
book[pos] = 1;
if(pos > 1 && !book[pos-1]) //要满足左边的盒子比他大,如果动过就代表比它小,不能移
{
int t = u-(1<<(3*i));
if(vis[t] == -1)
{
vis[t] = vis[u]+1;
q.push(t);
}
}
if(pos < n && !book[pos+1])
{
int t = u+(1<<(3*i));
if(vis[t] == -1)
{
vis[t] = vis[u]+1;
q.push(t);
}
}
}
}
}
void init()
{
memset(vis, -1, sizeof(vis));
for(int i = 1; i <= 7; i++)
bfs(i);
}
int a[10], Hash[10];
int main(void)
{
init();
int _;
cin >> _;
while(_--)
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]), Hash[i] = a[i];
sort(Hash+1, Hash+1+n);
int d = unique(Hash+1, Hash+1+n)-Hash-1;
for(int i = 1; i <= n; i++)
a[i] = lower_bound(Hash+1, Hash+1+d, a[i])-Hash-1;
int sta = 0;
for(int i = 1; i <= n; i++)
sta += i*(1<<(3*a[i]));
printf("%d\n", vis[sta]);
}
return 0;
}
盒子往没盒子的位置或大的盒子上移。求最小移动多少次后盒子能从小到大排列地放在每个位置(每个位置一个)(T<=6e3)
思路:因为n才7,所以容易想到状压。每个位置有3位二进制表示,所以一共需要2^21这么大的数组。状态表示第i个盒子所在的位
置。(因为盒子大小只与相对大小有关,所以一开始先将大小离散化成1-n)。因为T比较大,每次盒子只能向左放或者向右放,那
么我们从结束的位置开始搜索,bfs预处理出目标状态到所有状态所需要的最小步数,这样对于每个询问可以O(1)回答。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e6+5;
int vis[maxn];
bool book[15];
void bfs(int n)
{
queue<int> q;
int tmp = 0;
for(int i = 0; i < n; i++)
tmp += (i+1)*(1<<(3*i));
q.push(tmp);
vis[tmp] = 0;
while(!q.empty())
{
int u = q.front(); q.pop();
memset(book, 0, sizeof(book));
for(int i = 0; i < n; i++) //枚举第i+1个盒子,注意是从小的开始枚举
{
int pos = (u>>(i*3))%8;//第i+1个盒子所在位置
if(book[pos]) continue; //表示这个盒子上有比它小的盒子,所以不能移
book[pos] = 1;
if(pos > 1 && !book[pos-1]) //要满足左边的盒子比他大,如果动过就代表比它小,不能移
{
int t = u-(1<<(3*i));
if(vis[t] == -1)
{
vis[t] = vis[u]+1;
q.push(t);
}
}
if(pos < n && !book[pos+1])
{
int t = u+(1<<(3*i));
if(vis[t] == -1)
{
vis[t] = vis[u]+1;
q.push(t);
}
}
}
}
}
void init()
{
memset(vis, -1, sizeof(vis));
for(int i = 1; i <= 7; i++)
bfs(i);
}
int a[10], Hash[10];
int main(void)
{
init();
int _;
cin >> _;
while(_--)
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]), Hash[i] = a[i];
sort(Hash+1, Hash+1+n);
int d = unique(Hash+1, Hash+1+n)-Hash-1;
for(int i = 1; i <= n; i++)
a[i] = lower_bound(Hash+1, Hash+1+d, a[i])-Hash-1;
int sta = 0;
for(int i = 1; i <= n; i++)
sta += i*(1<<(3*a[i]));
printf("%d\n", vis[sta]);
}
return 0;
}
相关文章推荐
- ACM学习历程—Hihocoder 1233 Boxes(bfs)(2015北京网赛)
- hihoCoder 1233 Boxes(bfs)
- [置顶] HihoCoder 1233 Boxes(bfs打表)
- HihoCoder 1233 Boxes BFS
- hihoCoder 1233 Boxes(状态压缩 + bfs)——ACM-ICPC国际大学生程序设计竞赛北京赛区(2015)网络赛
- hihocoder 1233 Boxes(bfs+状态压缩+hash表)
- hiho 1233 Boxes(状态压缩+BFS)
- hihoCoder 1233 Boxes 哈希+最短路
- hihoCoder 1233 Boxes(状态压缩)
- hihoCoder 1233 Boxes(2015 北京网赛 G)
- HihoCoder - 1233 Boxes 状压 + bfs预处理
- hihoCoder 1233 Boxes
- hihocoder 1233 Boxes
- hiho1233--Boxes(BFS)
- hihocoder #1233 : Boxes 北京赛区(2015)网络赛(状态压缩+bfs)
- hihocoder Boxes 状压八进制bfs 加预处理
- hihocoder 北京网赛 boxs #1233 : Boxes
- HDU 1429 胜利大逃亡(续)(状压bfs)
- POJ 1475 Pushing Boxes (双重BFS/推箱子游戏)
- hihoCoder#1139(二分+bfs)