hihoCoder1233(2015北京网络赛H题)

来源:互联网 发布:java api 知乎 编辑:程序博客网 时间:2024/04/27 17:54

转载自:http://blog.csdn.net/queuelovestack/article/details/48625899


题意:

有n个卡槽,放有体积不同的n个空盒子,每次你可以移动一个空盒子到相邻卡槽,但前提是相邻卡槽若已经有空盒子,那么要移动的空盒子体积必须小于已有的空盒子,问要移动多少步才能使得从左到右,每个卡槽空盒子的体积递增。
现用①表示1号卡槽,②表示2号卡槽,依次类推……


思路:

状态压缩,状态表示每个盘子所在的位置,每个盘子的位置用三位二进制表示,总共的状态为2^21,因为每次盘子只能向左放或者向右放,那么我们从结束的位置开始搜索,bfs预处理出目标状态到所有状态所需要的最小步数,然后对于每个询问O(1)回答即可。


代码:

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-6#define LL long long#define pii pair<int, int>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;const int MAXN = 5000000;int n;int a[10], b[10];int vis[MAXN];bool fuck[10];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 s = q.front(); q.pop();memset(fuck, 0, sizeof(fuck));for(int i = 0; i < n; i++) { //i+1在哪个位置 int pos =  (s >> (3*i)) % 8;if(fuck[pos]) continue;fuck[pos] = 1;if(pos>1 && !fuck[pos-1]) {int t = s - (1<<(3*i));if(vis[t]==-1) {q.push(t);vis[t] = vis[s] + 1;} }if(pos<n && !fuck[pos+1]) {int t = s + (1<<(3*i));if(vis[t]==-1) {q.push(t);vis[t] = vis[s] + 1;}}}}}int main() {    //freopen("input.txt", "r", stdin);int T; cin >> T;memset(vis, -1, sizeof(vis));for(int i = 1; i <= 7; i++) bfs(i);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);for(int i = 1; i <= n; i++) a[i] = lower_bound(b+1, b+n+1, a[i]) - b - 1;int s = 0;for(int i = 1; i <= n; i++) {s += i*(1<<(3*a[i]));}printf("%d\n", vis[s]);}    return 0;}


0 0
原创粉丝点击