算法:DP
分析:NOIP2001年的第三题,看起来是很难做的一道题,但是经过转化就变得很容易了。
算出每一段区间内的单词个数,然后设f[i,j]是长度为i,分成j个部分所包含的最大的单词数,则f[i,j]=max(f[k,i-1]+leng[k+1,j])。
;{保证了单词的头不被重复使用的问题。} if (t>0) and (b[t]) then begin inc(calc); b[t]:=false; end; until t=0; end; exit(calc);end;procedure before;var i,j:longint;begin for i:=1 to len do begin for j:=1 to len do leng[i,j]:=calc(i,j); end;end;function max(x,y:longint):longint;begin if x>y then exit(x) else exit(y);end;procedure main;var i,j,k,t:longint;begin for i:=1 to m do{应该放在最外层,因为是分成几部分。} begin for j:=1 to len do begin for k:=j-1 downto i-1 do begin t:=leng[k+1,j]; f[j,i]:=max(f[j,i],f[k,i-1]+t); end; end; end;end;begin assign(input,'VJ1118.in'); reset(input); assign(output,'VJ1118.out'); rewrite(output); init; before; main; writeln(f[len,m]); close(input); close(output);end.
分析:NOIP2001年的第三题,看起来是很难做的一道题,但是经过转化就变得很容易了。
算出每一段区间内的单词个数,然后设f[i,j]是长度为i,分成j个部分所包含的最大的单词数,则f[i,j]=max(f[k,i-1]+leng[k+1,j])。
需要注意的是,区间的长度必须大于等于区间分成的部分。
program Vijos1118;
const
maxlen=200;
maxdic=6;
maxk=40;
var
f:array [0..maxlen,0..maxk] of longint;
leng:array [0..maxlen,0..maxlen] of longint;
dict:array [0..maxdic] of string;
b:array [0..maxlen] of boolean;
n,m,len,tot:longint;
s:string;
procedure init;
var
i:longint;
x:ansistring;
begin
s:='';
readln(n,m);
for i:=1 to n do
begin
readln(x);
s:=s+x;
end;
len:=length(s);
readln(tot);
for i:=1 to tot do readln(dict[i]);
end;
function calc(st,ed:longint):longint;{计算区间内的单词个数,这个是这道题的主要部分。}
var
i,t:longint;
temp,temp_:string;
begin
calc:=0;
for i:=1 to ed-st+1 do b[i]:=true;
temp:=copy(s,st,ed-st+1);
for i:=1 to tot do
begin
temp_:=temp;
repeat
t:=pos(dict[i],temp_);{找单词位置。}
temp_[t]:='
;{保证了单词的头不被重复使用的问题。} if (t>0) and (b[t]) then begin inc(calc); b[t]:=false; end; until t=0; end; exit(calc);end;procedure before;var i,j:longint;begin for i:=1 to len do begin for j:=1 to len do leng[i,j]:=calc(i,j); end;end;function max(x,y:longint):longint;begin if x>y then exit(x) else exit(y);end;procedure main;var i,j,k,t:longint;begin for i:=1 to m do{应该放在最外层,因为是分成几部分。} begin for j:=1 to len do begin for k:=j-1 downto i-1 do begin t:=leng[k+1,j]; f[j,i]:=max(f[j,i],f[k,i-1]+t); end; end; end;end;begin assign(input,'VJ1118.in'); reset(input); assign(output,'VJ1118.out'); rewrite(output); init; before; main; writeln(f[len,m]); close(input); close(output);end.