模擬賽9.4
阿新 • • 發佈:2020-09-06
#include <iostream> #include <string> using namespace std; int dfs1(int R,int P,int S)//石頭,布,剪刀 { if( R < 0 || P < 0 || S < 0 ) return -1;//有一類人數為負數即無解 if( R==0 && P==0 && S==0 ) return -1;//沒有人蔘加比賽也無解 if( R==1 && P==0 && S==0 ) return 0;//石頭贏 if( R==0 && P==1 && S==0 ) return 1;//布贏 if( R==0 && P==0 && S==1 ) return 2;//剪刀贏 return dfs1( (R-P+S)>>1,(R+P-S)>>1,(-R+P+S)>>1 );//遞迴(>>1:位運算,即除以2) } string dfs2(int t,int p) { if( p==1 )//當參賽只有2人時 { if( t==0 ) return "RS";//石頭贏 else if( t==1 ) return "PR";//布贏 else return "PS";//剪刀贏 } if( t==0 )//當石頭贏時(參賽者2人以上) { //既然這把是石頭贏了,那這一局肯定是石頭和剪刀的對決 //那麼上一局對決的兩組肯定是:石頭和剪刀,剪刀和布,才可能得到這一局的石頭和剪刀 string s1 = dfs2(2,p>>1);//遞迴,上一把是剪刀和布的對決,剪刀勝利 string s2 = dfs2(0,p>>1);//遞迴,上一把是石頭和剪刀的對決,石頭勝利 if( s1.compare(s2)>0 ) return s2+s1;//要求輸出字典序最小的 else return s1+s2; } else if( t==1 )//當布贏時(參賽者2人以上) { //既然這把是布贏了,那這一局肯定是布和石頭的對決 //那麼上一局對決的兩組肯定是:布和石頭,石頭和剪刀,才可能得到這一局的布和石頭 string s1 = dfs2(1,p>>1);//遞迴,上一把是布和石頭的對決,布勝利 string s2 = dfs2(0,p>>1);//遞迴,上一把是石頭和剪刀的對決,石頭勝利 if( s1.compare(s2)>0 ) return s2+s1;//要求輸出字典序最小的 else return s1+s2; } else//當剪刀贏時(參賽者2人以上) { //既然這把是剪刀贏了,那這一局肯定是剪刀和布的對決 //那麼上一局對決的兩組肯定是:剪刀和布,布和石頭,才可能得到這一局的剪刀和布 string s1 = dfs2(1,p>>1);//遞迴,上一把是布和石頭的對決,布勝利 string s2 = dfs2(2,p>>1);//遞迴,上一把是剪刀和布的對決,剪刀勝利 if( s1.compare(s2)>0 ) return s2+s1;//要求輸出字典序最小的 else return s1+s2; } } int main() { int R,P,S;//石頭,布,剪刀 cin >> R >> P >> S; int t = dfs1(R,P,S); if( t==-1 ) { cout<<"IMPOSSIBLE"<<endl; return 0; } string s = dfs2( t,(R+P+S)>>1 );//反向思考,根據結果還原每一輪。人數都是每一輪除以2 cout << s << endl; }