HihoCoder

来源:互联网 发布:新建视图 sql语句 编辑:程序博客网 时间:2024/06/06 08:33

传送门:HihoCoder - 1233

题意:有n个盒子放在n个放盒子的位置,每个盒子大小不一样,每次可以将一个盒子往它相邻的位置移懂,但是只能把小的盒子放到大的盒子上。求最少需要移动多少次之后盒子能从小到大排列地放在每个位置(每个位置一个)。

思路:从初始状态(从小到大排好)bfs所有的可能状态,并记录所需要的步数,状态的记录就是用三位二进制数(其实就是八进制)表示一个盒子的位置,这样所有状态就都可以在2^21内被表示出来了。

代码:

#include<bits/stdc++.h>#define ll long long#define pi acos(-1)#define MAXN 4000010#define inf 0x3f3f3f3fusing namespace std;typedef pair<int,int>P;int vis[MAXN], book[10];void bfs(int n){int val = 0, tmp, pos; queue<int> q;while(!q.empty()) q.pop();for(int i = 1; i <= n; i++) val += i * (1 << (3 * (i - 1)));vis[val] = 0;q.push(val);while(!q.empty()){memset(book, 0, sizeof(book));tmp = q.front(); q.pop();for(int i = 1; i <= n; i++){pos = (tmp >> (3 * (i - 1))) % 8;if(book[pos]) continue;book[pos] = 1;if(pos < n && !book[pos + 1]){val = tmp + (1 << (3 * (i - 1)));if(vis[val] == -1){vis[val] = vis[tmp] + 1;q.push(val);}}if(pos > 1 && !book[pos - 1]){val = tmp - (1 << (3 * (i - 1)));if(vis[val] == -1){vis[val] = vis[tmp] + 1;q.push(val);}}}}}int a[8], b[8];int main(){int T, n;memset(vis, -1, sizeof(vis));for(int i = 1; i <= 7; i++) bfs(i);cin >> T;while(T--){scanf("%d", &n);for(int i = 1; i <= n; i++)scanf("%d", a + i), b[i] = a[i];sort(b + 1, b + n + 1);int val = 0;for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)if(a[i] == b[j]){val += i * (1 << (3 * (j - 1)));break;}printf("%d\n", vis[val]);}    return 0;}


原创粉丝点击