题目
S计划送给J一枚戒指,以示他们的爱情天长地久
同时,S打算在戒指上刻写一些语句,以增加它的寓意。可惜戒指的大小有限,最多只能被刻入N个字母。细心的S非常了解J,知道她喜欢的单词,例如love, forever等等,同时他也知道这些单词都存在一个“愉悦值”,值越高的单词越能取悦J。
现在,S希望刻入一条字符串,使得各个单词在字符串中出现的次数 × 单词愉悦值之和尽可能的大。
1. 1 <= T <= 15
2. 1 <= N <= 50,1 <= M <= 100
3. 1 <= 单词长度 <= 10
4. 1 <= Hi <= 100
5. 数据保证不出现重复的单词
6. 对于每组数据输出一行,为在戒指上刻入的字符串。
如果有多解,则输出长度最短的解,若依然有多接则输出字典序最小的解。
答案有可能为空串。
分析
虽然这题的附加要求有很多:长度,字典序。
不过没关系,这题仍然可以用dp来处理。
具体的:
f[i,j]表示前i位,最后一个单词是第j个单词
我们再设same[i,j]表示第i个单词和第j个单词的重叠部分的长度
那么f[i+same[j,k],k]=max(f[i,j]+v[k],f[i+same[j,k],k])
而我们再记录两个值:
le[i,j],ans[i,j],分别表示前i位,最后一个单词是第j个单词的最大价值的最短长度的最小字典序的长度和字符串。
到此便可以很好的解决这个问题。
ps:我卡在这题很久的原因主要是same数组一直弄错。。还是要细心点,不要想当然,每一步都要经过严谨的思考来验证
var
t,i,j,k,ma,n,m,k1,k2:longint;
str:array[1..300] of string;
len,v:array[1..300] of longint;
c:array[1..500,1..300] of longint;
f,le:array[1..500,1..300] of longint;
ans:array[1..500,1..300] of string;we:string;
function max(l,r:longint):longint;
begin
if l<r then exit(r);exit(l);
end;
function get(x,y:string):longint;
var i,j,lenx,leny,an,st:longint;p:boolean;
begin
lenx:=length(x);leny:=length(y);an:=0;
if x=y then st:=2 else st:=1;
for i:=st to lenx do begin
if lenx-i+1>leny then continue;P:=true;
for j:=i to lenx do
if x[j]<>y[j-i+1] then begin p:=false;break;end;
if not p then continue;
an:=max(an,lenx-i+1);
end;exit(an);
end;
begin
readln(t);
for t:=1 to t do begin
readln(n,m);
for i:=1 to m do begin readln(str[i]);len[i]:=length(str[i]);end;
for i:=1 to m do
for j:=1 to m do begin
c[i,j]:=get(str[i],str[j]);
end;
fillchar(f,sizeof(f),0);
for i:=1 to 500 do
for j:=1 to 300 do ans[i,j]:='';
k:=k;
for i:=1 to m do begin
read(v[i]);
f[len[i],i]:=v[i];
ans[len[i],i]:=str[i];le[len[i],i]:=len[i];
end; readln;
for i:=1 to n do
for j:=1 to m do if f[i,j]>0 then
for k:=1 to m do begin
k2:=i+len[k]-c[j,k];
if f[k2,k]<f[i,j]+v[k] then begin
f[k2,k]:=f[i,j]+v[k];
k1:=len[k]-c[j,k];
ans[k2,k]:=ans[i,j]+copy(str[k],c[j,k]+1,k1);
le[k2,k]:=le[i,j]+k1;
end else
if (f[k2,k]=f[i,j]+v[k])and(le[k2,k]=le[i,j]+len[k]-c[j,k])and(ans[k2,k]>ans[i,j]+copy(str[k],c[j,k]+1,len[k]-c[j,k])) then begin
ans[k2,k]:=ans[i,j]+copy(str[k],c[j,k]+1,len[k]-c[j,k]);
le[k2,k]:=le[i,j]+len[k]-c[j,k];
end
else if (f[k2,k]=f[i,j]+v[k])and(le[k2,k]>le[i,j]+len[k]-c[j,k]) then begin
ans[k2,k]:=ans[i,j]+copy(str[k],c[j,k]+1,len[k]-c[j,k]);
le[k2,k]:=le[i,j]+len[k]-c[j,k];
end;
end;
ma:=0;we:='';
for i:=1 to n do
for j:=1 to m do
if ma<f[i,j] then begin ma:=f[i,j];we:=ans[i,j];end
else if (ma=f[i,j])and(we>ans[i,j]) then we:=ans[i,j];
writeln(we);
end;
close(input);close(output);
end.