2/50
1.挖地雷(DP)
var
begin
fillchar(a,sizeof(a),false);
fillchar(f,sizeof(f),0);
readln(n);
for i:=1 to n do read(w[i]);
readln(x,y);
while (x<>0)or(y<>0)do begin
a[x,y]:=true;
readln(x,y);
end;
f[n]:=w[n];
for i:=n-1 downto 1 do begin
l:=-1;
for j:=i+1 to n do
if a[i,j] and (f[j]>l) then begin
l:=f[j];
k:=j;
end;
r[i]:=k;
f[i]:=l+w[i];
end;
maxn:=1;
for i:=2 to n do
if f[i]>f[maxn] then maxn:=i;
writeln(f[maxn]);
write(maxn);
while r[maxn]<>0 do begin
write(‘-‘,r[maxn]);
maxn:=r[maxn];
end;
end.
题目规定所有路径都是单向的,满足无后效性和最优化原理
a[i,j]表示i,j两个地窖之间是否有路径
动态转移方程为:f[i]=max{w[i]+f[j]}
(i<j<=n,a[i,j]=true)
边界:f[n]=w[n]
推荐逆推嘿嘿嘿(个人喜好了)
2.合唱队形(DP)
var n,i,l,j,max:longint; b,a,f:array[1..1000] of longint; begin readln(n); fillchar(b,sizeof(b),0); for i:=1 to n do read(a[i]); b[1]:=1; for i:=2 to n do begin l:=0; for j:=1 to i-1 do if (a[j]<a[i])and(b[j]+1>l) then l:=b[j]; b[i]:=l+1; end; fillchar(f,sizeof(f),0); f[n]:=1; for i:=n-1 downto 1 do begin l:=0; for j:=i+1 to n do if (a[j]<a[i])and(f[j]+1>l) then l:=f[j]; f[i]:=l+1; end; max:=0; for i:=1 to n do if b[i]+f[i]>max then max:=b[i]+f[i]; dec(max); writeln(n-max); end.
从两边找最长上升子串。。
中间那个被算过两次,注意-1。。
原文:http://www.cnblogs.com/AlenaNuna/p/6273124.html