您的位置:首页 > 其它

hiho1233--Boxes(BFS)

2015-09-29 21:54 357 查看
题目大意:有n个盘子,n个柱子,每个柱子上都有一个盘子,任意两个盘子大小均不相同,一个盘子可以移动到相邻的柱子上,且必须比该柱子最上方的盘子要小,问最少移动多少次后,盘子从小到大依次摆在每个柱子上。

分析:首先,最少步的问题,说明,要用BFS。

          其次,多个起点,固定终点,说明,可以预处理,反向BFS。

          然后,就是考虑如何表示状态了。由于一个柱子上可以有多个盘子,所以,并不能有盘子的编号来表示状态。于是,我们可以考虑用每个盘子的位置表示当前的状态。又n最大为7,所以状态数最多8^7种。

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

#define maxn 11111111
int dp[maxn]; //从初始状态到每种状态的最小步数
int pos[10]; //pos[i] = j,表示第j个盘子在第i个位置
int dig[10]; //dig[i] = j,表示第i个盘子移动一次,状态变化j

void bfs(int x) {
int state, t, temp, head;
dig[x] = 1;
for(int i = x-1; i >= 1; i--)
dig[i] = dig[i+1]*8;
state = 0;
for(int i = 1; i <= x; i++)
state = state*8+i;
dp[state] = 0;
queue<int> q;
q.push(state);
while(!q.empty()) {
t = head = q.front();
q.pop();
memset(pos, 0, sizeof(pos));
for(int i = x; i >= 1; i--, t /= 8) //确定每个位置最上方的盘子
pos[t%8] = i;
for(int i = 1; i <= x; i++) {
if(pos[i] == 0) continue;
if(i > 1 && (pos[i] < pos[i-1] || !pos[i-1])) { //第i个盘子向前移
temp = head-dig[pos[i]];
if(dp[temp] == -1) {
dp[temp] = dp[head]+1;
q.push(temp);
}
}
if(i < x && (pos[i] < pos[i+1] || !pos[i+1])) { //第i个盘子向后移
temp = head+dig[pos[i]];
if(dp[temp] == -1) {
dp[temp] = dp[head]+1;
q.push(temp);
}
}
}
}
}

void init() {
memset(dp, -1, sizeof(dp));
for(int i = 1; i <= 7; i++)
bfs(i);
}

int main() {
init();
int n, T, loc[11111], a[10]; //loc[i]表示盘子i所在的位置
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
loc[a[i]] = i;
}
sort(a+1, a+n+1);
int st = 0;
for(int i = 1; i <= n; i++)
st = st*8 +loc[a[i]];
printf("%d\n", dp[st]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: