• 圆桌游戏


    【题目描述】

    有n个人围着圆桌坐成一圈,按顺时针顺序依次标为1~n号。对于i(1 < i < n)号来说,其左边为i+1号,右边为i-1号,1号右边为n号,n号左边为1号。

    每轮游戏会指定一个坐在圆桌边的人(设为i号),使其向左边的人(设为j号)发起挑战,若挑战成功,则j离开圆桌,若挑战失败,则i离开圆桌,当圆桌边只剩下一个人时,则其为最终胜利者。

    现已知,对于任意两个人i号、j号,若i向j发起挑战,结果是成功还是失败。假设每轮游戏可以随意指定发起挑战的人,询问哪些人可以成为最终胜利者。

    【输入描述】

    第一行输入一个整数n,表示参加游戏的人数;

    接下来n行,每行输入n个0或1,若第i行第j列为1,则表示i向j发起挑战会成功,否则表示挑战会失败,第i行第i列的值为0。

    【输出描述】

    输出一行数,表示可能成为最终胜利者的人的标号,标号按从小到大的顺序输出。

    【输入样例】

    3

    0 1 0

    0 0 1

    0 1 0

    【输出样例】

    1 3

    【数据范围及提示】

    样例解释:

    (1)先指定2号向3号发起挑战,3号离开;再指定1号向2号发起挑战,2号离开。此时1号是最终胜利者;

    (2)先指定1号向2号发起挑战,2号离开;再指定1号向3号发起挑战,1号离开。此时3号是最终胜利者;

    (3)无论如何安排挑战顺序,2号都无法成为最终胜利者。

    对于30%的数据,n ≤ 7;

    对于100%的数据,n ≤ 100。

    源代码:
    
    #include<cstdio>
    int n;
    bool i[201][201]={0},f[201][201]={0};
    int main() //区间型动态规划(环形)。
    {
        scanf("%d",&n);
        for (int a=1;a<=n;a++)
          for (int b=1;b<=n;b++)
          {
              scanf("%d",&i[a][b]);
              i[a][b+n]=i[a+n][b]=i[a+n][b+n]=i[a][b]; //i[][]表示挑战结果。
          }
        for (int a=1;a<(n<<1);a++) //f[][]表示两个人有没有可能相邻。
          f[a][a+1]=true;
        for (int a=(n<<1)-2;a>0;a--) //起点。
          for (int b=a+2;b<=(n<<1);b++) //终点。
            for (int c=a+1;c<b;c++) //中间点。
              if (f[a][c]&&f[c][b]&&(i[a][c]||!i[c][b])) //可能相邻且退出条件满足。
              {
                f[a][b]=true; //有可能相邻,中断。
                break;
              }
        for (int a=1;a<=n;a++)
          if (f[a][a+n]) //自己与自己有可能相邻,则符合题意。
            printf("%d ",a);
        return 0;
    }
    
    /*
        循环类似于环形石子合并。
        然后就从小区间枚举起点终点,逐渐扩大,中间点退出有两种情况,前点与其挑战赢,其与后点挑战输。
    */
  • 相关阅读:
    31、状态模式(详解版)
    33、中介者模式(详解版)
    36、备忘录模式(详解版)
    34、迭代器模式(详解版)
    30、责任链模式(职责链模式)详解
    29、命令模式(详解版)
    32、观察者模式(Observer模式)详解
    37、解释器模式(详解版)
    35、访问者模式(Visitor模式)详解
    28、策略模式(策略设计模式)详解
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5968812.html
Copyright © 2020-2023  润新知