【动态规划】【poj 1836】Alignment

问题

有一列士兵排队,给出其身高a[i],现在要让队列中的一些士兵出列,使得剩下的每个士兵都能够看到对头或队尾(在该士兵和他看到的队尾之间没有比该士兵高的士兵)。现在要求最少的出对的士兵数。

分析

乍一看很像最长xx序列,但是又没有思路,需要抽象题目中的模型。假设a[i]是满足要求的队列中的元素,那么假设a[1]是左边的对首,a[1]~a[i]中的元素都比a[i]小,也就是说a[1]~a[i]的元素都可以满足要求。那么在a[i]的右边的元素只可能比a[i]大或者小,如果比a[i]小,那么从该元素一直到队尾一定是递减的,才能满足题目要求。

这样一来,问题就转化成:在队列a[i]中找到一个元素,使得a[1]<a[2]<a[3]<……a[i]>a[i+1]>a[i+2]…..>a[n]即可。这样就很像合唱队形问题,只需要两遍最长上升序列即可,然后枚举最值。但是还有一种特殊情况要考虑,就是最高的元素可能是两个即a[1]<a[2]<a[3]<……a[i]=[i+1]>a[i+2]…..>a[n]当然只有两个时是满足题意的(一旦三个同样高,中间的就会被两边的挡住)。这样一来问题就解决了。

code

program liukee;
var
  f1,f2:array[0..1000] of longint;
  a:array[0..1000] of double;
  i,j,n,ans:longint;

function max(a,b:longint):longint;
begin
  if a>b then exit(a) else exit(b);
end;

begin
  readln(n);
  for i:=1 to n do
    read(a[i]);
  for i:=1 to n do
  begin
    f1[i]:=1;
    f2[i]:=1;
  end;
  for i:=1 to n do
    for j:=i-1 downto 1 do
      if a[j]<a[i] then
        f1[i]:=max(f1[i],f1[j]+1);
  for i:=n downto 1 do
    for j:=i+1 to n do
      if a[j]<a[i] then
        f2[i]:=max(f2[i],f2[j]+1);
  for i:=1 to n do
  begin
    ans:=max(ans,f1[i]+f2[i]-1);
    for j:=i+1 to n do
      if a[i]=a[j] then
      ans:=max(ans,f1[i]+f2[j]);
  end;
  writeln(n-ans);
end.

反思

想到了基本模型,但没有抽象成正确解。没有考虑特殊情况。

遇到熟悉的提醒要先考虑共性,再按照题目要求完成问题的转化。最后要考虑题目的特殊性。

posted @ 2011-05-27 17:23  liukee  阅读(425)  评论(0编辑  收藏  举报