圆桌游戏

12 篇文章 0 订阅

【问题描述】
有一种圆桌游戏是这样进行的: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个空格隔开。

【输入输出样例】
game.in game.out
3
0 1 0
0 0 1
0 1 0   1 3

【输入输出样例说明】
先指定2号向3号发起挑战,3号离开;再指定1号向2号发起挑战,2号离开。此时1号是最终胜利者。
先指定1号向2号发起挑战,2号离开;再指定1号向3号发起挑战,1号离开。此时3号是最终胜利者。
无论如何安排挑战顺序,2号都无法成为最终胜利者。

【数据规模与约定】
对于30%的数据,n≤7
对于100%的数据,n≤100

老是把标题看成圆桌骑士
大概因为第六特异点还没过
小莫终于能上场怼爹了

以为是个图论题
其实是我Dio哒!
其实是个DP

首先把它拆成一条链
设f[i][j]表示i与j能否相邻
则如果f[i][i+n]为真
i就可能为胜者

枚举i到j之间最后一个出局的人k
i - k – j
k有两种出局方式
i挑战k成功
k挑战j失败

如果存在一个k
使得i能与k相邻
k能与j相邻
且k可能以以上两种方式中的一种出局
说明i和j可以相邻

然而

忘了倒着枚举

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<climits>
#include<string>
#include<cstdlib>
#include<ctime>
#define MOD 1000000007
#define LL long long
using namespace std;

int n,i,j,k,ch[205][205],f[205][205];

int main()
{
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);

    scanf("%d",&n);

    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        {
            scanf("%d",&ch[i][j]);          
            ch[i+n][j+n]=ch[i][j];
            ch[i+n][j]=ch[i][j];
            ch[i][j+n]=ch[i][j];
        }

    for(i=1;i<=2*n;i++)
        f[i][i+1]=1;        

    for(i=2*n;i>=1;i--)
        for(j=i+1;j<=2*n;j++)
            for(k=i+1;k<=j-1;k++)
                if(f[i][k]&&f[k][j])
                    if(ch[i][k]||!ch[k][j]) f[i][j]=1;

    for(i=1;i<=n;i++)
        if(f[i][i+n]) printf("%d ",i);      

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值