题目链接点这里codeforces1567B
题意:不久将举行国际象棋比赛,届时将有 n
位国际象棋选手参加。 每个参与者将与其他参与者进行一场比赛。 每场比赛的结果要么是一个玩家赢,另一个玩家输,要么是双方平局。每个玩家对锦标赛都有自己的期望,他们可以是以下两种类型之一:玩家不想输掉任何一场比赛(即以零损失完成比赛);玩家想要赢得至少一场比赛。您必须确定是否存在所有比赛的结果,以便所有玩家都满足他们的期望。 如果有多种可能的结果,请打印其中任何一个。 如果没有,请报告这是不可能的。
输入
第一行包含一个整数 t
(``1≤t≤20`)——测试用例的数量。
每个测试用例的第一行包含一个整数 n
(2≤n≤50
)——棋手的数量。
第二行包含字符串 s
(|s|=n; si∈{1,2}
)。 如果 si=1
,则第 ii 个玩家有第一种类型的期望,否则为第二种类型。
输出
对于每个测试用例,按以下格式打印答案:
在第一行,如果无法满足所有玩家的期望,则打印 NO
。
否则,打印 YES
,并在接下来的 n
行中打印大小为 n×n
的矩阵。
第 i
行第 j
列中的矩阵元素应等于:
+,如果第i
名玩家在与第 j
名玩家的比赛中获胜;
- 如果第 i
名玩家在与第 j
名玩家的比赛中输了;
=,如果第 i
和第 j
名玩家的比赛结果为平局;
X,如果 i=j
。
思路
按题目要求初始化矩阵,对角线为X
,其余位置先为-
。
首先判断是否能完成要求,如果去除要求平局的点,右上三角形除斜边之外的其他点的数量如果不小于想至少获胜一局的人的数量,就能够完成。否则则不能完成要求。如果可以完成则搜索数字串,每一行从首位开始,如果遇到一个2
,让第一个点改为+
;每当改完一个点之后,让这一行之后的全为-
;最后进行一次批处理。+
和-
在对角线两侧是相互对立的。至此,我们完成了胜负表的绘制。详细代码如下:
#include<bits/stdc++.h>
using namespace std;
int t,n;
char s[60];
char a[60][60];
int cnt=0;
void init0(int n)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
a[i][j]='-';
for(int i=0;i<n;i++){a[i][i]='X';}
}
void init1(int u)
{
for(int i=0;i<n;i++)
{
if(i==u||a[u][i]=='=')continue;
a[u][i]='=';cnt++;
}
for(int i=0;i<n;i++)
{
if(i==u||a[i][u]=='=')continue;
a[i][u]='=';cnt++;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
cin>>t;
while(t--)
{
cnt=0;
int tt=0;
cin>>n>>s;
init0(n);
for(int i=0;i<n;i++)
{
if(s[i]=='1')
{
tt++;
init1(i);
}
}
int aa;
for(int i=0;i<n;i++)
{
aa=0;
for(int j=i+1;j<n;j++)
{
if(a[i][j]=='-'&&aa==0)
{
a[i][j]='+';
aa=1;
}
else if(a[i][j]=='-')a[j][i]='+';
}
}
tt=n-tt;
int ans=(n*n-n)/2;
cnt/=2;
ans-=cnt;
for(int i=0;i<n;i++){a[i][i]='X';}
if(ans<tt)cout<<"NO"<<endl;
else{
cout<<"YES"<<endl;
for(int uu=0;uu<n;uu++)
{
for(int hh=0;hh<n;hh++)
cout<<a[uu][hh];
cout<<endl;
}
}
}
}