1.路面修整(making the grade)

http://poj.org/problem?id=3666

http://61.187.179.132/JudgeOnline/problem.php?id=1592

   首先需要预处理,即将所有的高度离散,转化为数组b,b[i]表示第i大的数

    用f[i,j]表示到第i个点,更改后高度是第j大的数,则朴素的方程是f[i,j]:=min{f[i-1,k]+abs(a[i]-b[j]),其中需要枚举的变量是i,j,k(增减性通过控制k的大小,k小于j为增,大于j为减),时间复杂度为n3,显然会超时。

    优化:扩大定义范围,即f[i,j]表示到第i个点,高度小于等于(或大于等于)第j大的数,此时方程为f[i,j]:=min{f[i-1,j]+abs(a[i]-b[j]);需要分别两次求,一次递增一次递减,时间复杂度将为n2

    由于题目有问题,所以只对一种情况进行求解就可以过

code:

program second;
var
   n,i,j,ans : Longint;
   a,b         : array[1..3000] of longint;
   f         : array[0..2300,0..2100] of longint;
procedure init;
var
   t : longint;
begin
   readln(n);
   for i:=1 to n do
   begin
      readln(a[i]);
      b[i]:=a[i];
   end;
   for i:=1 to n-1 do
      for j:=i+1 to n do
     if b[i]>b[j] then
     begin
        t:=b[i];
        b[i]:=b[j];
        b[j]:=t;
     end;
end; { init }
function min(x,y : longint):longint;
begin
   if x<y then
      exit(x)
   else
      exit(y);
end; { min }
function max(x,y : longint):longint;
begin
   if x>y then exit(x)
   else
      exit(y);
end; { max }
procedure work;
begin
   fillchar(f,sizeof(f),127);
   for i:=1 to n do
      f[0,i]:=0;
   for i:=1 to n do
      for j:=1 to n do
      begin
     f[i,j]:=min(f[i,j],f[i-1,j]+abs(a[i]-b[j]));
     f[i,j]:=min(f[i,j],f[i,j-1]);
      end;
   ans:=maxlongint;
   for i:=1 to n do
      ans:=min(ans,f[n,i]);
end; { work }
begin
   assign(input,'grading.in'); reset(input);
   assign(output,'grading.out'); rewrite(output);
   init;
   work;
   writeln(ans);
   close(input);
   close(output);
end.

2.整数划分

http://acm.nankai.edu.cn/p1046.html

   对于这道题也先说一下朴素的方法,f[i,j]表示拆分第i个数,j为拆出来的最大的数,则f[i,j]:=Σf[i-j,k]时间复杂度为n3

   运用上面提到的方法,我们也可以优化,f[i,j]表示拆分第i个数,拆除的最大的数小于等于j,此时方程为f[i,j]:=f[i,j-1]+f[i-j,j],时间复杂度将为n2

code:

program haha;
var
   n,i,j,ans : longint;
   f	     : array[0..90,0..90] of longint;
procedure work;
begin
   for i:=1 to 80 do
   begin
      f[i,1]:=1;
      f[0,i]:=1;
   end;
   for i:=1 to 80 do
      for j:=2 to 80 do
      begin
	 if i>=j then
	    f[i,j]:=f[i-j,j]+f[i,j-1];
         if j>i then
            f[i,j]:=f[i,j-1];
      end;
end; { work }
begin
   assign(INput,'sdf.in'); reset(input);
   work;
   while not eof do
   begin
      ans:=0;
      readln(n);
      writeln(f[n,n]);
   end;
end.
posted on 2012-03-14 18:15  淡·雅·墨  阅读(288)  评论(0编辑  收藏  举报