DP专题——括号序列

毕竟是个渣,写完一遍之后又按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天,
我天嘞困死了……

posted on 2015-09-29 23:09  Chuckqgz  阅读(...)  评论(...编辑  收藏

导航