• 周六. 4 月 25th, 2026

物嫩软件资讯网

软件资讯来物嫩

hluoj 1153 格斗

admin@wunen

5 月 19, 2025


问题描述

:格斗俱乐部是格斗爱好者的一个组织,在这里,格斗者们能通过与别的成员进行格斗来释放自己的压力与轻松自己的情绪。最近俱乐部举行了一场比赛,该比赛有N位选手参加,他们将围成一个圆圈,每一场比赛圈内任意的两位相邻的选手均可进行相互的格斗,胜利者将留在圈内进入下轮比赛而失败者则直接被送往医院(没有平局)。比赛是残酷的,最后圈内将只剩下一位选手,他将是总冠军。我们做个奇怪的假设,两位选手进行格斗,他们比赛的结果总是确定的。虽然俱乐部的成员们都很喜欢格斗,但是他们仍然很希望能获得总冠军。现在你通过统计已经知道了任意两位选手格斗的结果,你有责任告诉每位选手,如果赛程合适安排的话,他是否可能成为总冠军。


输入描述

:数据第一行是一个整数N,(1<=N<=40),表示比赛的选手数量。接下来给出一个N∗N的“0”、“1”矩阵A(行内用空格隔开),第 i 行第 j 列为1 表示选手 i 能战胜选手 j ,否则选手 j 能战胜选手 i 。

你可以假定 Aij 与 Aji(i≠j)均是不同的且Aii=0。比赛开始时所有选手按顺时针方向由编号1到编号N站成一个圈,初始时编号1与编号N的选手是相邻的。


输出描述

:输出包含N行,每行为一个整数“0”或“1”,“1”表示第i号选手有可能成为冠军,“0”表示不可能。


输入样例



3

0 1 1

0 0 1

0 0 0


输出样例



1

0

0


题解

:首先有一个环形的结构,操作中要倍长。由于是可不可能获胜,而且是相邻两个决斗然后合并,满足区间性质,考虑区间dp。设一个 f[ i ][ j ][ k ] 表示在区间 i 到 j 中 k 可不可能获胜。k 在这个区间中能获胜 是不是应该在 i 和 j 区间中 找到一个截点分成两个区间,在左区间中 k 胜出, 在右区间中的胜出者若 k 能战胜它 则 f[ i ][ j ][ k ] 为 1 ,否则 f[ i ][ j ][ 右区间的获胜者 ] 为 1。 所以枚举有 枚举区间长度,区间起点, 区间中的截点 , 左区间的获胜者, 右区间的获胜者。


code

#include<bits/stdc++.h>
 using namespace std;
int n;
int a[100][100];
int f[100][100][100];
int main()
{
  freopen("data.in","r",stdin);
  freopen("data.out","w",stdout);
  
  cin>>n;
  for(int i = 1 ; i <= n;i ++)
   for(int j = 1 ; j <= n;j ++) 
    scanf("%d",&a[i][j]);
    
  for(int  i = 1 ; i <= n ;i++)
    f[i][i][i] = 1 ,f[i+n][i+n][i] = 1 ;
  
  for(int i = 2 ; i <= n ; i++)
   for(int j = 1 ; j <= 2*n-i+1 ; j++)
   {
   	int st = j ,ed = i+j-1;
   	for(int mid = st ; mid < ed; mid ++)
   	 for(int l = 1 ;l <= n ; l++)
   	 if(f[st][mid][l])
   	 {
   	  for(int r = 1 ; r <= n; r++)
	   if(f[mid+1][ed][r])
	   {
	    if(a[l][r]) f[st][ed][l] = 1 ;
		  else f[st][ed][r] = 1 ;	
	   }   	 	
	 }
   }
  for(int i = 1 ;i <= n ;i ++)
   {
   	bool flag = 1 ;
   	for(int j =1 ; j <= n && flag; j++)
   	 if(f[j][j+n-1][i]) {printf("1\n"); flag = 0 ;}
   	if(flag) printf("0\n");
   }
  return 0;
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注