题目
问题描述
有
n
n
n个人参加比赛,两两之间进行对决,每两个人之间都会进行一次比赛;
对决有三种结果:要么胜,要么败,要么平。
选手有两种策略:
第一种:全场不败,稳扎稳打;
第二种:但求一胜,败局不论。
在选手给出自己选择的策略后,问是否存在一种局面使得所有选手都满足自身策略。
若不存在,则输出"NO";
若存在,则输出"YES",并以
n
∗
n
n*n
n∗n的矩阵输出结果。
∗
*
∗,表示自己与自己对决;
+
+
+,表示行序号代表的选手赢了列序号代表的选手;
−
-
−,表示行序号代表的选手输给了列序号代表的选手;
=
=
=,表示行序号代表的选手与列序号代表的选手打平;
分析
先分析两种策略,
策略一,表示对决结果只能为胜利或平局;
策略二,表示允许失败和平局,但至少赢一局。
对于采取策略一的选手来说,对决结果可以为胜利或平局,但为了不对采取策略二的选手造成影响,将他们的对局情况都安排为平局是最好的。
对于采取策略二的选手来说,他们与采取策略一的选手对决结果此时满足平局,所以他们的胜局必须要依靠同样采取策略二的选手:
当采取策略二的人数为0时,和和气气,大家都是平局,满足条件;
当采取策略二的人数只有一个人时,这位选手找不到同样采取策略二的对手,所以不存在;
当采取策略二的人数为两个人时,两个人之间只会对决一次,一战定胜负,无法双赢,从而必有一人无法满足策略二,所以不存在;
当采取策略二的人数大于二时,可以进行相互成全,让每个采取策略二的人都获得一次胜利(这也许就是演戏吧),满足条件。
之后我们按这个模拟一下即可,先将策略一的选手的情况的安排好,再处理选择策略二的选手,给他们安排好一次胜局后,就可以把他其余还没有结果的比赛都安排为负局。
代码
#include <bits/stdc++.h>
using namespace std;
int t;
int n;
string s;
char a[55];
char b[55][55];
int main(){
cin>>t;
while(t--){
cin>>n;
memset(b,0,sizeof b);
int a1=0,a2=0;
cin>>s;
for(int i=1;i<=n;i++){
a[i]=s[i-1]-'0';
b[i][i]='X';
if(a[i]==1)a1++;
else a2++;
}
if(a2==2||a2==1){
cout<<"NO"<<endl;
continue;
}
cout<<"YES"<<endl;
for(int i=1;i<=n;i++){
if(a[i]==1){
for(int j=1;j<=n;j++){
if(j==i)continue;
b[i][j]=b[j][i]='=';
}
}
}
for(int i=1;i<=n;i++){
int ans=0;
if(a[i]==2){
for(int j=1;j<=n;j++){
if(j==i)continue;
else if(b[i][j]=='+'&&ans==0)
ans=1;
else if(!b[i][j]&&ans==0){
b[i][j]='+';
b[j][i]='-';
ans=1;
}
else if(!b[i][j]&&ans==1){
b[i][j]='-';
b[j][i]='+';
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<b[i][j];
}
cout<<endl;
}
}
return 0;
}