2015北京网络赛 G题 Boxes bfs

#1233 : Boxes

时间限制: 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
一看到这个题目我就知道要用广搜,只是不知道怎么判重。
从来没有想到要开这么高维flag7[8][8][8][8][8][8][8]的数组
搜索还是太差了,后面听同学说用高维数组判重,还是搞了几个小时。
这个关键在高维判重。
其他的详见代码
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
        
        
#include
        
        
          using namespace std; int flag7[8][8][8][8][8][8][8]; int flag6[7][7][7][7][7][7]; int flag5[6][6][6][6][6]; int flag4[5][5][5][5]; int flag3[4][4][4];//flag3[i][j][k]表示当箱子只有3个,第一个在i位置,第二个在j位置,第三个在k位置时移动到降序状态所要的最小步数。 struct node//表示状态 { int a[8];//a[i]表示第i+1大的箱子在的位置 int num;//移动到降序状态所要的最小步数 }; queue 
         
           que; int flag(int n, int a[], int num)//保存当前状态,避免重复 { switch(n) { case 7: flag7[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ][ a[5] ][ a[6] ] = num;break; case 6: flag6[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ][ a[5] ] = num;break; case 5: flag5[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ] = num;break; case 4: flag4[ a[0] ][ a[1] ][ a[2] ][ a[3] ] = num;break; case 3: flag3[ a[0] ][ a[1] ][ a[2] ] = num;break; break; } return 0; } int returnFlag(int n, int a[])//返回当前状态对应的值 { switch(n) { case 7: return flag7[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ][ a[5] ][ a[6] ]; case 6: return flag6[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ][ a[5] ]; case 5: return flag5[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ]; case 4: return flag4[ a[0] ][ a[1] ][ a[2] ][ a[3] ]; case 3: return flag3[ a[0] ][ a[1] ][ a[2] ]; } return 0; } int f(int n, int a[]) { while(!que.empty()) que.pop(); node t; int i, j; for(i = 0; i < n; i++) t.a[i] = a[i]; t.num = 0; flag(n, t.a, t.num+1);//赋值 que.push(t); bool cnt[8];//防止大的放到小的上面 int dir[] = {1, -1}; int qwe = 0; while(!que.empty()) { t = que.front();que.pop(); memset(cnt, 0, sizeof(cnt)); for(i = 0; i < n; i++) { for(j = 0; j < 2; j++) { int tmp = t.a[i]+dir[j]; if(tmp >= 0 && tmp < n && !cnt[tmp] && !cnt[t.a[i]])//!cnt[tmp] (防止大的放到小的上面), !cnt[t.a[i]](防止小的箱子下面的大箱子移动) { int temp = t.a[i]; t.num++; t.a[i] = tmp; if(!returnFlag(n, t.a))//判重,对没有的状态标记,并且入队,这里标记就不会出现相同的状态在同时在队列中。 { flag(n, t.a, t.num+1); que.push(t); } t.a[i] = temp; t.num--; } } cnt[ t.a[i] ] = 1; } } return 0; } struct NUM { int num; int val; }; bool cm(NUM x, NUM y) { return x.val < y.val; } int main(void) { int T; int i; int a[8]; for(i = 0; i < 7; i++) a[i] = i; for(i = 3; i < 8; i++) f(i, a); NUM b[8]; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); for(i = 0; i < n; i++) { scanf("%d", &b[i].val); b[i].num = i; } sort(b, b+n, cm); for(i = 0; i < n; i++) { a[i] = b[i].num; } if(n == 1) { printf("0\n");continue; } if(n == 2) { if(a[0] > a[1]) printf("-1\n"); else printf("0\n"); continue; } switch(n) { case 7: printf("%d\n", flag7[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ][ a[5] ][ a[6] ]-1);break; case 6: printf("%d\n", flag6[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ][ a[5] ]-1);break; case 5: printf("%d\n", flag5[ a[0] ][ a[1] ][ a[2] ][ a[3] ][ a[4] ]-1);break; case 4: printf("%d\n", flag4[ a[0] ][ a[1] ][ a[2] ][ a[3] ]-1);break; case 3: printf("%d\n", flag3[ a[0] ][ a[1] ][ a[2] ]-1);break; } } return 0; } 
          
        
       
       
      
      
     
     
    
    

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值