石头剪刀布

【题目描述】

wzms 今年举办了一场剪刀石头布大赛,bleaves 被选为负责人。
比赛共有 
2
n
2n 个人参加, 分为 n 轮,
在每轮中,第 1 位选手和第 2 位选手对战,胜者作为新的第 1 位选手,
第 3 位和第 4 位对战,胜者作为新的第 2 位选手,以此类推。
bleaves 调查得知,每个人都有其偏爱决策,每个人在每一次对战中都会使用他的偏爱决策。
如果一次对战的双方的偏爱决策相同,那么这次对战就永远不会结束,所以 bleaves 不希望这种情况发生。
现在 bleaves 知道了每个人的偏爱决策,但她不知道如何安排初始的次序,使得上面的情况不会发生,你能帮帮她吗?

【输入描述】

一行三个整数 R,P,S ,表示偏爱石头,布,剪刀的人数分别为 R,P,S 。

【输出描述】

如果无解,输出 `IMPOSSIBLE` ;
否则输出一个长度为 R+P+S 的字符串,第 i 个字符表示初始时第 i 位选手的偏爱决策,
如果有多种方案,输出字典序最小的。

【样例】

示例1

输入
1 1 0
输出
PR
说明
只有 2 个选手,一个偏爱石头,一个偏爱布,无论次序如何,偏爱布的选手都会胜出。
所以方案可以是 PR 和 RP ,其中字典序最小的 PR 。

示例2

输入
2 0 0
输出
IMPOSSIBLE

示例3

输入
1 1 2
输出
PSRS

思路:已知胜者的选择可以推出败者的选择,深搜枚举最终获胜者的偏爱选择即可,由于要按字典序输出,因此要递归获取

【源代码】

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 1000000+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;
int judge(int a, int b, int c) {
    if(a<0||b<0||c<0)
        return -1;
    if(a==0&&b==0&&c==0)//平手
        return -1;
    if(a==1&&b==0&&c==0)//石头
        return 0;
    if(a==0&&b==1&&c==0)//布
        return 1;
    if(a==0&&b==0&&c==1)//剪刀
        return 2;
    return judge((a+c-b)>>1,(b+a-c)>>1,(c+b-a)>>1);
}
string getAns(int x,int d) {
    if(d==1) {
        if(x==0)//石头
            return "RS";
        else if(x==1)//布
            return "PR";
        else//剪刀
            return "PS";
    }
    if(x==0) {
        string s1=getAns(2,d>>1);
        string s2=getAns(0,d>>1);
        if(s1.compare(s2)>0)
            return s2+s1;
        else
            return s1+s2;
    }
    else if(x==1) {
        string s1=getAns(1,d>>1);
        string s2=getAns(0,d>>1);
        if(s1.compare(s2)>0)
            return s2+s1;
        else
            return s1+s2;
    }
    else {
        string s1=getAns(1,d>>1);
        string s2=getAns(2,d>>1);
        if(s1.compare(s2)>0)
            return s2+s1;
        else
            return s1+s2;
    }
}
int main() {
    LL a, b, c;
    scanf("%lld%lld%lld",&a,&b,&c);
    int res=judge(a,b,c);
    if(res==-1)
        cout<<"IMPOSSIBLE"<<endl;
    else{
        string str=getAns(res,(a+b+c)>>1);
        cout<<str<<endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值