分段dp: 特点:有阶段性 举例:用m个木板覆盖
for 阶段数i
for 前一次完成的终点j
for 这次完成的终点k
dp[i][k]=min(dp[i][k],dp[i-1][j]+cost{j+1 to k})
区间dp: 特点:区间连续
for 区间长度l
for 区间起点i {
区间终点 j=i+l-1;
for 区间分隔点k
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
}
双尾dp:
例题: [USACO 5.4.2]周游加拿大
代码:
var
n,m,i,j,k,ans:
longint
;
map:
Array
[
0..105
,
0..105
]
of
boolean
;
city:
array
[
0..105
]
of
string
;
s,ss:
string
;
b:
array
[
0..105
]
of
boolean
;
dp:
array
[
0..105
,
0..105
]
of
longint
;
function
max(a,b:
longint
):
longint
;
begin
if
a>b
then
exit(a);exit(b);
end
;
begin
readln(n,m);
for
i:=
1
to
n
do
begin
readln(s);
s:=s+
' '
;
for
j:=
1
to
length(s)
do
if
(s[j]<=
'z'
)
and
(s[j]>=
'a'
)
or
(s[j]<=
'Z'
)
and
(s[j]>=
'A'
)
or
(s[j]<=
'9'
)
and
(s[j]>=
'0'
)
then
continue
else
break;
city[i]:=copy(s,
1
,j-
1
);
end
;
for
i:=
1
to
m
do
begin
readln(s);
ss:=copy(s,
1
,pos(
' '
,s)-
1
);
delete(s,
1
,pos(
' '
,s));
s:=s+
' '
;
for
j:=
1
to
length(s)
do
if
(s[j]<=
'z'
)
and
(s[j]>=
'a'
)
or
(s[j]<=
'Z'
)
and
(s[j]>=
'A'
)
or
(s[j]<=
'9'
)
and
(s[j]>=
'0'
)
then
continue
else
break;
s:=copy(s,
1
,j-
1
);
for
j:=
1
to
n
do
if
city[j]=ss
then
break;
for
k:=
1
to
n
do
if
city[k]=s
then
break;
map[j,k]:=
true
;
map[k,j]:=
true
;
end
;
dp[
1
,
1
]:=
1
;
for
i:=
1
to
n
do
for
j:=i+
1
to
n
do
begin
for
k:=
1
to
j-
1
do
if
map[j,k]
and
(dp[i,k]<>
0
)
then
dp[i,j]:=max(dp[i,j],dp[i,k]+
1
);
dp[j,i]:=dp[i,j];
end
;
ans:=
1
;
for
i:=
1
to
n
do
if
map[i,n]
then
ans:=max(ans,dp[i,n]);
writeln
(ans);
end
.