• AcWing 258. 石头剪子布


    N 个小朋友(编号为 0,1,2,…,N−1)一起玩石头剪子布游戏。

    其中一人为裁判,其余的人被分为三个组(有可能有一些组是空的),第一个组的小朋友只能出石头,第二个组的小朋友只能出剪子,第三个组的小朋友只能出布,而裁判可以使用任意手势。

    你不知道谁是裁判,也不知道小朋友们是怎么分组的。

    然后,孩子们开始玩游戏,游戏一共进行 M 轮,每轮从 N 个小朋友中选出两个小朋友进行猜拳。

    你将被告知两个小朋友猜拳的胜负结果,但是你不会被告知两个小朋友具体使用了哪种手势。

    比赛结束后,你能根据这些结果推断出裁判是谁吗?

    如果可以的话,你最早在第几轮可以找到裁判。

    输入格式
    输入可能包含多组测试用例

    每组测试用例第一行包含两个整数 N 和 M。

    接下来 M 行,每行包含两个整数 a,b,中间夹着一个符号(>,=,<),表示一轮猜拳的结果。

    两个整数为小朋友的编号,a>b 表示 a 赢了 b,a=b 表示 a 和 b 平手,a

    输出格式
    每组测试用例输出一行结果,如果找到裁判,且只能有一个人是裁判,则输出裁判编号和确定轮数。

    如果找到裁判,但裁判的人选多于 1 个,则输出 Can not determine。

    如果根据输入推断的结果是必须没有裁判或者必须有多个裁判,则输出 Impossible。

    具体格式可参考样例。

    数据范围
    1≤N≤500,
    0≤M≤2000

    输入样例:
    3 3
    0<1
    1<2
    2<0
    3 5
    0<1
    0>1
    1<2
    1>2
    0<2
    4 4
    0<1
    0>1
    2<3
    2>3
    1 0
    输出样例:
    Can not determine
    Player 1 can be determined to be the judge after 4 lines
    Impossible
    Player 0 can be determined to be the judge after 0 lines

    思路:

            这一题一共又三种情况,石头、剪刀、布,并且题目中明确告诉我们除了裁判外,每个人都是固定的种类,然后每个人会相互存在大小关系,比如A>B,B>C,那么根据游戏规则我们肯定可以知道C>A,分三种情况,因此可以用带权并查集。

            然后本题还有一个裁判机制,裁判可以随便出,对于一个有裁判在的对局,由于裁判可以随便出,所以时可能照成矛盾的,但是除了裁判所在对局的其他对局,关系都是合法的。

           

            因此我们可以枚举所有人去找裁判。

            对于每个人,枚举不包括这个人的对局

            1.如果这些对局都是合法的,说明这个人可能时裁判,裁判人数+1

            2.如果遇到第一个不合法的对局,说明这个人不是裁判,这时候需要记录这是第几局,因为一直到这一局,是判断这个人不是裁判的依据

           

            最终会得出可能的裁判人数:

            1.裁判人数>1 ,可能有多个裁判,输出不确定

            2.裁判人数=1 ,只有一个裁判,需要输出裁判的编号和最早确定他是裁判的轮数,我们需要确定其他所有人不是裁判才能确定当前人是裁判。 因此需要枚举其他所有不是裁判的人,从最早判断它们不是裁判的轮数中取一个最大值,就是最早能排除其他人确定当前人是裁判的位置。

            3.裁判人数=0 没有裁判,输出没有

            代码:

    1. #include
    2. using namespace std;
    3. const int N=1e5+10;
    4. int n,m;
    5. int p[N],d[N];
    6. bool st[N];//记录每个人是否是裁判
    7. int f[N];//记录第i个人最早判定不是裁判的轮数
    8. int a[N],b[N];// 第i轮对局是谁对谁
    9. char c[N];//记录第i局对局的关系
    10. int find(int x) {
    11. if(x!=p[x]) {
    12. int root=find(p[x]);
    13. d[x]+=d[p[x]];
    14. d[x]%=3;
    15. p[x]=root;
    16. }
    17. return p[x];
    18. }
    19. bool check(int k) { //判断第k轮对局是否合法
    20. int x=a[k],y=b[k];//首先取出两人编号
    21. int t=1;//记录大小关系,><是1,=是0
    22. if(c[k]=='=')t=0;
    23. if(c[k]=='>')swap(x,y);//保证x
    24. int px=find(x),py=find(y);
    25. if(px==py) { //在同一集合,判断是否合法
    26. if((d[x]-d[y]+3)%3!=t) {
    27. //说明不合法
    28. return false;
    29. }
    30. } else {
    31. //说明不在同一集合
    32. p[px]=py;
    33. d[px]=(t+d[y]-d[x]+3)%3;
    34. }
    35. return true;
    36. }
    37. int main() {
    38. while(cin>>n>>m) {
    39. //读入操作人,和操作次数
    40. for(int i=1; i<=m; i++) {
    41. cin>>a[i]>>c[i]>>b[i];
    42. }
    43. memset(f,0,sizeof f);//初始化每个人判定不是裁判的轮数
    44. int cnt=0,num=0;//cnt表示可能是裁判的人数,num表示裁判编号
    45. for(int i=0; i//枚举所有人
    46. for(int j=0; j0;//初始化并查集和关系
    47. bool flag=true;//判断当前人是否可能是裁判
    48. for(int j=1; j<=m; j++) { //枚举对局
    49. if(a[j]!=i&&b[j]!=i&&!check(j)) {
    50. //cout<
    51. //不符合题意的对局,说明这个人不是裁判
    52. flag=false;
    53. f[i]=j;
    54. break;
    55. }
    56. }
    57. if(flag) { //说明这个人可能是裁判
    58. cnt++;
    59. num=i;
    60. }
    61. }
    62. if(!cnt)puts("Impossible"); //没有裁判
    63. else if(cnt>1)puts("Can not determine"); //多个裁判
    64. else {
    65. int res = 0; //记录最早能确定裁判的轮数
    66. for(int i = 0; i < n; i++) //枚举所有人
    67. if(i != num) //如果当前人不是裁判
    68. res = max(res, f[i]); //更新最早确定轮数
    69. printf("Player %d can be determined to be the judge after %d lines\n", num, res);
    70. }
    71. }
    72. return 0;
    73. }

  • 相关阅读:
    Spring构造注入的几种方式
    DNS域名解析服务
    Bindiff安装以及使用
    oracle将restful接口封装到视图中
    「PAT乙级真题解析」Basic Level 1103 (问题分析+完整步骤+伪代码描述+提交通过代码)
    MyBatis基于XML的详细使用-参数、返回结果 处理
    OpenLayers 实现画点、画线、画面、画圆
    Docker 实用操作文档
    【Try Hack Me】内网专项---Wreath
    数据挖掘的学习路径
  • 原文地址:https://blog.csdn.net/qq_64214980/article/details/127722008