FZU 1603 Checkers II

Checkers II
Time Limit:5s Memory limit:32M
Accepted Submit:41 Total Submit:184

It is easy for us to solve " Checkers" using the formula . Now the problem has a little changed .
Figure 1:

Oaiei’s new problem is showed as follows :

  1. The chessboard is a straight line which has N lattices.
  2. There are two kinds of chesses and one empty lattice in the chessboard.
  3. The initial state will be given arbitrarily.
  4. There are two possible ways of moving :
    • a chess can move directly to the adjacent empty lattice
    • a chess can jump over one lattice into the next empty lattice
  5. The end state will be given arbitrarily too.
  6. The state is in the following format:
    • @ represents the first kind of chesses
    • # represents the second kind of chesses
    • & represents the empty lattice
    • @ and # have the same number
  7. When you change the initial state into the end state, the game is over.
Your task is coming. Give you the initial state and the end state, and you should calculate the minimum move steps you have done to change the initial state into the end state.

Input

The first line is an integer T(T<=35), means the number of test cases. Following T lines, each line contain two strings A and B which have the same size N(N is a positive odd integer which is less than 21). A indicates the initial state and B indicates the end state.

Output

For each test case, print the integer number which indicting the minimum move steps.

Sample Input

1
##&@@ @@&##

Sample Output

8 

Hint

The one of solutions in the example with the minimum move steps is shown as follows:


represents ‘#’
represents ‘@’
represents ‘&’





题目意思很简单就是问从初状态到末状态要几步,赤裸裸的BFS换来的只能是TLE,当然数据太弱了可能稍微优化下就可以过了,不过只要数据稍微加强一些,那么暴力BFS显然不是一个好的策略;

由于题目的特点,赤裸裸的提示我们使用2进制保存状态,运算速度大大提高,提高为原来的至少N倍左右.

偶的:
1 61(10) 2008-12-12 20:47:10 187 ms 10204 K C++ 2133B AekdyCoin

















由于棋子只有2种,'#','@',很容易就把'@'看为0,'#'看为'1',那么除了空格'&'以外可以得到一个长度不超过(19-1)=18的2进制数,算出来最多也就(1<<18),而且肯定达不到这么大(1和0的数目相同,最大就是111...000(就是1和0相同个数的状态)),而'&'只与1个,于是就可以开个HASH[(1<<18)][19]
第一维保存的是hash状态值,第二维表示的是'&'后面的有效棋子的个数(0..len-1,len表示输入的字符串的长度).

下面问题就是状态转化的时候需要特别注意:
1.把'&'作为参考点,于是题目所谓的'can move directly to the adjacent empty lattice ',对于这个,很容易发现其hash状态值是不变的,仅'&'的位置发生了变化,就是说'&'后面的棋子的个数变化了.
于是简简单单就处理完了第一种方式.
2.把'&'作为参考点,注意实际上这个操作可以看成2进制里面的2位数的交换,处理使用位运算便可。



参考代码:
  1. #include<iostream>
  2. #include<stack>
  3. using namespace std;
  4. #define inhash(n) (hash[n.val][n.pos])
  5. #define showans(a) (printf("%d/n",a))
  6. bool hash[1<<18][19];
  7. struct Node
  8. {
  9.     int val;
  10.         short step,pos;
  11.     bool operator==(const Node&n)const{return val==n.val&&pos==n.pos;}
  12. }q[950000],tmp,F,D;
  13. int f,r,tlen,ans,bin[21]={1},low_a,low_b;
  14. char A[21],B[21];
  15. inline Node in(char *str)
  16. {
  17.     int i,key=0;
  18.     tmp.step=0;
  19.     for(i=0;str[i];i++)if(str[i]!='&')key=key*2+(str[i]!='@');else tmp.pos=tlen-i-1;
  20.     tmp.val=key;
  21.     return tmp;
  22. }
  23. inline int lowbit(int val,int pos){return (val&bin[pos])!=0;}
  24. inline bool init()
  25. {
  26.     memset(hash,false,sizeof(hash));
  27.     f=r=ans=0;
  28.     scanf("%s%s",A,B);
  29.     if(strcmp(A,B)==0)return false;
  30.     tlen=strlen(A);
  31.     D=in(B);
  32.     return true;
  33. }
  34. inline void solve()
  35. {
  36.     F=in(A);
  37.     q[r++]=F;
  38.     hash[F.val][F.pos]=true;
  39.     while(f<r)
  40.     {
  41.         tmp=q[f++];
  42.         tmp.step++;
  43.                 if(tmp.pos+2<tlen)
  44.         {
  45.             F=tmp;
  46.             low_a=lowbit(F.val,F.pos+1);
  47.             low_b=lowbit(F.val,F.pos);
  48.             if(low_a!=low_b)F.val+=low_a*bin[F.pos]+low_b*bin[F.pos+1]-low_a*bin[F.pos+1]-low_b*bin[F.pos];
  49.             F.pos+=2;
  50.             if(!inhash(F))
  51.             {
  52.                 if(F==D) {ans=F.step;return;}
  53.                 hash[F.val][F.pos]=true;
  54.                 q[r++]=F;
  55.             }
  56.         }
  57.         if(tmp.pos-2>=0)
  58.         {
  59.             F=tmp;
  60.             low_a=lowbit(F.val,F.pos-2);
  61.             low_b=lowbit(F.val,F.pos-1);
  62.             if(low_a!=low_b)F.val+=low_a*bin[F.pos-1]+low_b*bin[F.pos-2]-low_a*bin[F.pos-2]-low_b*bin[F.pos-1];
  63.             F.pos-=2;
  64.             if(!inhash(F))
  65.             {
  66.                 if(F==D) {ans=F.step;return;}
  67.                 hash[F.val][F.pos]=true;
  68.                 q[r++]=F;
  69.             }
  70.         }
  71.         if(tmp.pos+1<tlen)
  72.         {
  73.             F=tmp;
  74.             F.pos++;
  75.             if(!inhash(F))
  76.             {
  77.                 if(F==D) {ans=F.step;return;}
  78.                 hash[F.val][F.pos]=true;
  79.                 q[r++]=F;
  80.             }
  81.         }
  82.         if(tmp.pos-1>=0)
  83.         {
  84.             F=tmp;
  85.             F.pos--;
  86.             if(!inhash(F))
  87.             {
  88.                 if(F==D) {ans=F.step;return;}
  89.                 hash[F.val][F.pos]=true;
  90.                 q[r++]=F;
  91.             }
  92.         }
  93.     }
  94. }
  95. int main()
  96. {
  97.     int T,i;
  98.     for(i=1;i<=20;i++)bin[i]=bin[i-1]*2;
  99.     scanf("%d%*c",&T);
  100.     while(T--)
  101.     {
  102.         if(init())solve();else ans=0;
  103.         showans(ans);
  104.     }
  105.     return 0;
  106. }

你可能感兴趣的:(FZU 1603 Checkers II)