这道题目我的做法是差分约束,具体地,设s[i]表示1..i的一个前缀和,那么对于输入的a[x][y],
如果a[x][y]='+',说明s[y]比s[x-1]要大,s[y]>s[x-1] s[y]-s[x-1]>=1,所以从x-1到y连一条长度为1的边
如果a[x][y]='-',说明s[y]比s[x-1]要大,s[y]<s[x-1] s[x-1]-s[y]>=1,所以从y到x-1连一条长度为1的边
如果a[x][y]='0',说明s[y]和s[x-1]一样大,s[y]=s[x-1] s[y]-s[x-1]=0,所以从x-1到y连一条长度为0的边。虽然是等号而不是不等号,但是如果s[y]<>s[x-1],则会出现正权回路,和题设矛盾。
这样建完图后,跑一遍最长路,求出s后,原始序列就显而易见了。
下附AC代码:
const
mo=100;
var
a:array[-1..15,-1..15] of longint;
d:array[-1..100] of longint;
h:array[0..100] of longint;
bo:array[-1..100] of boolean;
s:string;
n,tt,i,j,k,head,tail,u:longint;
begin
readln(tt);
while tt>0 do
begin
tt:=tt-1;
readln(n);
readln(s);
k:=0;
fillchar(a,sizeof(a),200);
for i:=1 to n do
for j:=i to n do
begin
k:=k+1;
case s[k] of
'+':a[i-1,j]:=1;
'-':a[j,i-1]:=1;
'0':a[i-1,j]:=0;
end;
end;
fillchar(d,sizeof(d),200); d[-1]:=0;
fillchar(bo,sizeof(bo),true);
for i:=0 to n do
a[-1,i]:=0;
head:=0; tail:=1; h[1]:=-1;
while head<tail do
begin
head:=head mod mo+1;
u:=h[head]; bo[u]:=true;
for i:=0 to n do
if a[u,i]>-1000000 then
if d[u]+a[u,i]>d[i] then
begin
d[i]:=d[u]+a[u,i];
if bo[i] then
begin
tail:=tail mod mo+1;
h[tail]:=i; bo[i]:=false;
end;
end;
end;
for i:=1 to n-1 do write(d[i]-d[i-1],' '); writeln(d[n]-d[n-1]);
end;
end.
2015.2.11
by lych