下午閒來無事,突然想起收藏夾裏塵封多年的題目,都是些比較感興趣的題目,隨便看了道2829 binary strings。
思路:顯然是一個搜索題。狀態映射到數組dist[1<<20]。考慮[i,j],i=j沒有意義,於是每次最多操作有20*19/2=190種,每次都要操作到若干位,按平均10位算大致是1900次,大致3步耗時就比較多了,故用雙向廣搜。
A*算法估價函數不好寫。。。
雙廣注意第一次搜到的結果不一定是最優解!
附代碼如下:
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <iostream>
- #include <string>
- #include <math.h>
- #include <vector>
- #include <queue>
- using namespace std;
- /************************************************************************/
- /* 雙向廣搜 */
- /************************************************************************/
- inline bool get(int &t)
- {
- bool flag = 0 ;
- char c;
- while(!isdigit(c = getchar())&&c!='-') if( c == -1 ) break ;
- if( c == -1 ) return 0 ;
- if(c=='-') flag = 1 , t = 0 ;
- else t = c ^ 48;
- while(isdigit(c = getchar())) t = (t << 1) + (t << 3) + (c ^ 48) ;
- if(flag) t = -t ;
- return 1 ;
- }
- #define REP(n) for( i = 0 ; i < n ; i++)
- const int maxn = 1 << 20 ;
- int dist[maxn] , len ;
- char st[32] , goal[32] ;
- int getValue(char str[])
- {
- int i , j = 0 ;
- REP(strlen(str)) j = ( j << 1 ) + ( str[i] ^ 48 ) ;
- return j ;
- }
- int getPos(int i,int j,int key) // i <= j
- {
- int ii , ans = 0 ;
- for( ii = i ; ii <= j ; ii++) ans += ( key & ( 1 << ii ) ) ;
- return ans ;
- }
- int getAntiPos(int i,int j,int key) // i <= j
- {
- int ii , ans = 0 ;
- int k = i+j ;
- for( ii = i ; ii <= j ; ii++) ans += ( ( key & ( 1 << ii ) ) > 0 ) ? ( 1 << (k-ii) ) : 0 ;
- return ans ;
- }
- void initArray(int array[])
- {
- int i ;
- REP((1<<len)) array[i] = -1 ;
- }
- int binSearch()
- {
- queue<int> head , tail ;
- head.push(getValue(st)) ;
- tail.push(getValue(goal)) ;
- priority_queue<int,vector<int>,greater<int> > ans ;
- ans.push(0x7fffffff);
- int i , j , k , kk ;
- while (1)
- {
- int uHead , uTail ;
- uHead = head.front(); head.pop();
- uTail = tail.front(); tail.pop();
- //printf("%d\n",ans.top());
- if( ans.top() <= (dist[uHead]+((1<<len)^dist[uTail])+1) ) return ans.top();
- for( i = 0 ; i < len ; i++)
- for( j = i+1 ; j < len ; j++)
- {
- //reverse[i,j] of head and tail
- k = uHead - getPos(i,j,uHead) + getAntiPos(i,j,uHead) ;
- kk = uTail - getPos(i,j,uTail) + getAntiPos(i,j,uTail) ;
- if( dist[k] >= (1<<len) )
- {
- ans.push(( dist[k] ^ ( 1 << len ) ) + dist[uHead] + 1 );
- }
- if( dist[kk] > 0 && dist[kk] < (1<<len) )
- {
- ans.push( dist[kk] + ( dist[uTail] ^ ( 1 << len ) ) + 1 );
- }
- if( dist[k] == -1 )
- {
- dist[k] = dist[uHead] + 1 ;
- head.push(k) ;
- }
- if( dist[kk] == -1 )
- {
- dist[kk] = dist[uTail] + 1 ;
- tail.push(kk) ;
- }
- }
- }
- }
- void solve()
- {
- len = strlen(st) ;
- initArray(dist) ;
- dist[getValue(st)] = 0 ;
- dist[getValue(goal)] = ( 1 << len ) ;
- if(getValue(st)==getValue(goal)) puts("0");
- else printf("%d\n",binSearch());
- }
- int main()
- {
- int t ;
- get(t);
- while (t--)
- {
- scanf("%s%s",st,goal);
- solve();
- }
- }