zoukankan      html  css  js  c++  java
  • 【NOIp模拟赛】圆桌游戏

    【问题描述】

             有一种圆桌游戏是这样进行的:n个人围着圆桌坐成一圈,按顺时针顺序依次标号为1号至n号。对1<i<n的i来说,i号的左边是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。

     

    【输出】

             一行,包含若干个数,表示可能成为最终胜利者的玩家的标号。标号按从小到大的顺序输出,相邻两个数间用1个空格隔开。

     

    【输入输出样例1】

    game.in

    game.out

    3

    0 1 0

    0 0 1

    0 1 0

    1 3

             见选手目录下的game / game1.in与game / game1.out

     

    【输入输出样例1说明】

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

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

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

     

    【输入输出样例2】

             见选手目录下的game / game2.in与game / game2.out

     

    【数据规模与约定】

    对于30%的数据,n≤7

    对于100%的数据,n≤100

    分析

    30分,暴力搜索即可

    100分,用f[i][j]表示第i个人与第j个人是否可以相邻,我们可以枚举i,j中间的一个人k。若i和j能相邻得满足两个条件:

    1.i和k可以相邻,k和j可以相邻.

    2.i能挑战成功k或者k挑战不成功j.

    最后由于这是一个环,我们得把它拆成n*2的一条链。

    代码

    暴力搜索的代码就不放了

    100分

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=200+5;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int n;
    int s[maxn];
    bool f[maxn][maxn],mp[maxn][maxn];
    int main()
    {
        freopen("game.in","r",stdin);
        freopen("game.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            mp[i][j]=read();
        for(int i=1;i<=n;i++)
        s[i]=s[i+n]=i;
        for(int i=1;i<n+n;i++)
        f[i][i+1]=1;
        for(int i=n+n-2;i>=1;i--)
        for(int j=i+2;j<=n+n;j++)
        for(int k=i+1;k<j;k++)
        if(f[i][k]&&f[k][j]&&(mp[s[i]][s[k]]||!mp[s[k]][s[j]]))
        {
            f[i][j]=1;
            break;
        }
        for(int i=1;i<=n;i++)
        if(f[i][i+n]) printf("%d ",i);
        return 0;
    }
    欢迎转载,转载请注明出处!
  • 相关阅读:
    Linux安全加固
    mosquitto
    Docker设置2375端口
    linux shell 常见的时间戳操作
    tar打包并且排除log目录
    spring boot2整合shiro安全框架实现前后端分离的JWT token登录验证
    http post
    scp命令 Linux和Windows文件互传
    git did not exit cleanly (exit code 1) 的解决办法
    windows安装TortoiseGit详细使用教程【基础篇】
  • 原文地址:https://www.cnblogs.com/huihao/p/7441010.html
Copyright © 2011-2022 走看看