原题:
http://172.16.0.132/senior/#contest/show/1916/3
题目描述:
格斗俱乐部是格斗爱好者的一个组织,在这里,格斗者们能通过与别的成员进行格斗来释放自己的压力与轻松自己的情绪。最近俱乐部举行了一场比赛,该比赛有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
分析:
假设需要判断x是否能赢得整场战斗,把环看成链,x点拆成两个,那编号为x的人能从所有人中胜出的充分必要条件是他能与自己“相遇”。这样,在连续几个人的链中,只须考虑头尾两个人能否胜利会师,中间的则不予考虑。设meet[I,j]记录I和j能否相遇,能则为true,否则为false,则问题转化为了找到一个k,使得i和k ,k和j均能相遇(这里实际上是递归求解!),而i或者j能打败k。即,状态转移方程为
Meet[I,j]:=true 存在i
实现:
var
n,m,t,i,j,k,l:longint;
a,meet:array[0..87,0..47]of boolean;
bz:array[0..87]of longint;
begin
readln(n);
for i:=1 to n do
for j:=1 to n do
begin
read(m);
a[i,j]:=(m=1);
end;
for l:=1 to n do
begin
for i:=1 to n+1 do bz[i]:=(l+i-2)mod n+1;
fillchar(meet,sizeof(meet),false);
for i:=1 to n do meet[i,i+1]:=true;
for t:=2 to n do
for i:=1 to n+1-t do
begin
j:=i+t;
for k:=i+1 to j-1 do
if(meet[i,k] and meet[k,j])and(a[bz[i],bz[k]] or a[bz[j],bz[k]])then meet[i,j]:=true;
end;
if meet[1,n+1] then writeln(1) else writeln(0);
end;
end.