毕竟是个渣,写完一遍之后又按LRJ的写了一遍,再写了一遍递归版,最终加上输出解部分
括号序列
定义如下规则序列(字符串):
空序列是规则序列;
如果S是规则序列,那么(S)和[S]也是规则序列;
如果A和B都是规则序列,那么AB也是规则序列。
例如,下面的字符串都是规则序列:
(), [], (()), ([]), ()[], ()[()]
这几个则不是规则序列:
(, [, ], )(, ([()
现在,给出一些由‘(’,‘)’,‘[’,‘]’构成的序列,请添加尽量少的括号,得到一个规则序列。
分析
- 很容易想到的递归版本
uses
math;
var
s:string;
function answer(l,r:longint):longint;
var mini,k:longint;
begin
if l=r then exit(1)
else if (s[l]='(')and(s[r]=')')or(s[l]='[')and(s[r]=']') then exit(answer(l+1,r-1))
else if l<r then begin
mini:=maxint;
for k:=l to r-1 do
mini:=min(mini,answer(l,k)+answer(k+1,r));
exit(mini);
end else exit(0);
end;
begin
readln(s);
writeln(answer(1,length(s)));
end.
- 稍微做下改动,同时为了方便输出解(输出时再判定一次)
d(s)表示s的解
现存在两种情况
当s形为(s')时,转移到d(s')
当length(s)>1 时,转移到d(sA)+d(sB)
边界条件
length(s)=1时 d(s)=1
其他为0
{2015-9-24 括号序列}
{program by Chuck}{误}
program noip_dp_1;
uses
math;
const
maxn=1000;
type
LL=longint;
var
d:array[1..maxn,1..maxn] of LL;
i,j,k,n:LL;
st:ansistring;
boo:boolean;
function match(l,r:char):boolean;
begin
if (l='(') and (r=')') or (l='[') and (r=']') then exit(true)
else exit(false);
end;
procedure print(l,r:Longint);
var
k,ans:longint;
begin
if l>r then exit;
if l=r then
begin
if (st[l]=')')or(st[l]='(') then write('()')
else write('[]');
exit;
end;
ans:=d[l][r];
if match(st[l],st[r]) and (ans=d[l+1][r-1])then begin
write(st[l]);
print(l+1,r-1);
write(st[r]);
end else
for k:=l to r-1 do
if ans=d[l][k]+d[k+1][r] then
begin
print(l,k);
print(k+1,r);
exit;
end;
end;
begin
assign(input,'dp1.in');
assign(output,'dp1.out');
reset(input);
rewrite(output);
readln(st);
n:=length(st);
fillchar(d,sizeof(d),0);
for i:=1 to n do
d[i][i]:=1;
for i:=n-1 downto 1 do
for j:=i+1 to n do
begin
d[i][j]:=n;
boo:=match(st[i],st[j]);
if boo then
d[i][j]:=min(d[i][j],d[i+1][j-1]);
for k:=i to j-1 do
d[i][j]:=min(d[i][j],d[i][k]+d[k+1][j]);
end;
writeln(d[1][n]);
print(1,n);
close(input);
close(output);
end.
为了这个程序煞费苦心,我真是渣渣到爆了……
自己好不容易写的一大段因为head hole big open被删了,删完才发现稍作改动就是对的啊……
于是因为生病实在没有坚持下来,看了题解再打的一遍。。
明天九月最后一天,距离初赛还有11天,
我天嘞困死了……