NOIP2002 字串變換題解(雙向搜索)
阿新 • • 發佈:2017-08-09
操作 exit empty 數據 turn int open oid def
65. [NOIP2002] 字串變換
時間限制:1 s 內存限制:128 MB
[問題描述]
已知有兩個字串A$, B$及一組字串變換的規則(至多6個規則):
A1$ -> B1$
A2$ -> B2$
規則的含義為:在A$中的子串A1$可以變換為B1$、A2$可以變換為B2$…。
例如:A$=‘abcd‘ B$=‘xyz‘
變換規則為:‘abc’->‘xu’ ‘ud’->‘y’ ‘y’->‘yz’
則此時,A$可以經過一系列的變換變為B$,其變換的過程為:
‘abcd’->‘xud’->‘xy’->‘xyz’
共進行了三次變換,使得A$變換為B$。
[輸入]
A$ B$
A1$ B1$
A2$ B2$ |->變換規則
... ... /
所有字符串長度的上限為20。
[輸出]
若在10步(包含10步)以內能將A$變換為B$,則輸出最少的變換步數;否則輸出"NO ANSWER!"
[輸入樣例]
abcd xyz abc xu ud y y yz
[輸出樣例]
3
在這裏膜拜一下wq大佬,強行bfs藐視數據,我就比較慘了,打了好幾次,正著搜反著搜都會T某個點,這就比較尷尬了,於是乎,我們引進了雙向搜索這個概念。
我們可以把寬搜想像為一棵樹,為了方便計算,我們暫定它為二叉樹好了,如果我要搜10層,我單項搜索,會有2047個節點,但如果我雙向搜索,就只有63+63==126個節點了,由此可見,雙向可以說是完爆單向的,何況這只是二叉樹。
於是這道題在雙向搜索的前提下就無比簡單了,我們把A,B分別塞進兩個隊列,同時廣搜,直到兩者相遇。至於修改操作嗎,string就可以搞定了。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 #include<queue> 8 #include<string> 9 #include<cmath> 10 using namespace std; 11 string a,b; 12 string A[10View Code],B[10]; 13 struct st{ 14 string x; 15 int js; 16 }; 17 int js; 18 queue<st> q1; 19 bool yx; 20 int p=12345,q=10000007; 21 unsigned long long xp[50]; 22 int fw[2][10000007]; 23 bool get_hash(st x,int be){ 24 unsigned long long has=0; 25 for(int i=x.x.length()-1;i>=0;i--) 26 { 27 has=has*p+int(x.x[i]); 28 } 29 has%=q; 30 if(fw[be][has]) 31 return 1; 32 fw[be][has]=x.js; 33 if(fw[be^1][has]) 34 { 35 printf("%d\n",x.js+fw[be^1][has]); 36 exit(0); 37 } 38 return 0; 39 } 40 queue<st> q2; 41 void bfs(){ 42 while(!q1.empty()&&!q2.empty()) 43 { 44 st aa=q1.front(); 45 q1.pop(); 46 if(aa.js>6) 47 { 48 yx=1; 49 printf("NO ANSWER!\n"); 50 return; 51 } 52 for(int i=1;i<=js;i++) 53 { 54 int la=-1; 55 for(int j=0;j<=aa.x.length();j++) 56 { 57 long long t=aa.x.find(A[i],j); 58 if(t>=0&&t<=20&&t!=la) 59 { 60 la=t; 61 j=la-1; 62 st c; 63 c.x=aa.x; 64 c.x.replace(t,A[i].length(),B[i]); 65 c.js=aa.js+1; 66 if(c.x.length()<=20&&!get_hash(c,0)&&c.js<=10) 67 { 68 q1.push(c); 69 } 70 } 71 } 72 } 73 st bb=q2.front(); 74 q2.pop(); 75 if(bb.js>6) 76 { 77 yx=1; 78 printf("NO ANSWER!\n"); 79 return; 80 } 81 for(int i=1;i<=js;i++) 82 { 83 int la=-1; 84 for(int j=0;j<=bb.x.length();j++) 85 { 86 long long t=bb.x.find(B[i],j); 87 if(t>=0&&t<=20&&t!=la) 88 { 89 la=t; 90 j=la-1; 91 st c; 92 c.x=bb.x; 93 c.x.replace(t,B[i].length(),A[i]); 94 c.js=bb.js+1; 95 if(c.x.length()<=20&&!get_hash(c,1)&&c.js<=10) 96 { 97 q2.push(c); 98 } 99 } 100 } 101 } 102 } 103 } 104 int main(){ 105 cin>>a>>b; 106 js=1; 107 while(cin>>A[js]>>B[js]) 108 { 109 js++; 110 } 111 js--; 112 st xx; 113 xx.x=a; 114 xx.js=0; 115 q1.push(xx); 116 get_hash(xx,0); 117 st yy; 118 yy.x=b; 119 yy.js=0; 120 q2.push(yy); 121 get_hash(yy,1); 122 xp[0]=1; 123 for(int i=1;i<=20;i++) 124 { 125 xp[i]=xp[i-1]*p; 126 } 127 bfs(); 128 if(!yx) 129 printf("NO ANSWER!\n"); 130 //while(1); 131 return 0; 132 }
NOIP2002 字串變換題解(雙向搜索)