DP小结

分段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.

你可能感兴趣的:(DP)