標籤:
題目連結:http://poj.org/problem?id=3087
題目大意:給定三堆牌,前兩堆數目均為c,第三堆數目為2*c。
給定洗牌規則,問經過多少次洗牌才能到達第三堆牌的狀態。如果不可能到第三堆牌的狀態,輸出-1。
解題思路:bfs類比。
用字串描述牌的狀態。用set來標記該字串是否出現過,如果第二次出現,說明已經陷入了迴圈,不可能得到結果。
開始先把s1和s2洗完,步數加一,放進set。然後判斷該狀態是否滿足,如果不滿足,則將該牌按規則分開,再次洗牌。
直到洗完的牌的狀態滿足了所要求的狀態。輸出結果。如果沒有結果,則迴圈過程中該狀態一定會重複出現。則將step置為-1.跳出迴圈。
代碼入下:
1 #include<cstdio> 2 #include<string> 3 #include<set> 4 #include<iostream> 5 using namespace std; 6 7 int c,step; 8 char s1[105],s2[105],s[210];//記錄三個串 9 set<string> vis;//用來判重,防止陷入死迴圈10 11 string shuffle(string s1,string s2)//洗牌一次,得到新的牌12 {13 string temp="";14 for(int i=0;i<c;i++)15 {16 temp+=s2[i];17 temp+=s1[i];18 }19 return temp;20 }21 22 void bfs()23 {24 vis.clear();25 26 string temp=shuffle(s1,s2);//洗一次牌27 vis.insert(temp);//標記這種結果出現過了28 step=1;//步數加一29 30 while(temp!=s)//一直洗牌31 {32 temp=shuffle(temp.substr(0,c),temp.substr(c,c));//將temp牌分開,再次洗牌33 step++;//步數加一34 if(vis.find(temp)!=vis.end())//如果得到的這種結果以前已經出現過了,說明無論如何得不到題目中所要求的結果35 {36 step=-1;37 break;38 }39 vis.insert(temp);//將該結果標記40 }41 printf("%d\n",step);//輸出總的步數42 }43 44 int main()45 {46 int cases;47 int num=1;48 scanf("%d",&cases);49 while(cases--)50 {51 cin>>c>>s1>>s2>>s;52 printf("%d ",num++);53 bfs();54 }55 return 0;56 }View Code
專題一 簡單搜尋 Problem G