[USACO08FEB]修路Making the Grade

[USACO08FEB]修路Making the Grade
比较难的dp,比赛时打的找LIS,然后其他的尽可能靠近,40分。
先举个例子
6
1 2 3 1 4 5
6
1 2 3 3 4 5
第4个1要么改成3,要么改成4,反正是数列中的数。
所以最优情况下,答案中的数都是原数列中有的。
b[]是a[]由小到大排序之后的数组
令f[i][j]表示使前i个数成为不减的最小花费,而且第i个的高度为b[j].
f[i][j]=min(f[i-1][k])+abs(a[i]-b[j]);1<=k<=n
k从1~n递增,一个显然的优化就是单调队列,递增的,每次取队首。
不增同理。

AC:

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#define inf 2147483647
#define For(i,a,b) for(register int i=a;i<=b;i++)
#define p(a) putchar(a)
#define g() getchar()
//by war
//2017.10.18
using namespace std;
int f[2010][2010];
int q[2010];
int a[2010];
int b[2010];
int l,r;
int ans;
int n;
int m;
void in(int &x)
{
    int y=1;
    char c=g();x=0;
    while(c<'0'||c>'9')
    {
    if(c=='-')
    y=-1;
    c=g();
    }
    while(c<='9'&&c>='0')x=x*10+c-'0',c=g();
    x*=y;
}
void o(int x)
{
    if(x<0)
    {
        p('-');
        x=-x;
    }
    if(x>9)o(x/10);
    p(x%10+'0');
}
int main()
{
    in(n);
    For(i,1,n)
    in(a[i]),b[i]=a[i];
    sort(b+1,b+n+1);
    m=unique(b+1,b+n+1)-b-1;
    For(i,1,n)
      {
          r=0;
          For(j,1,m)
        {
            while(r&&f[i-1][j]<=f[i-1][q[r]])r--;
            q[++r]=j;
            f[i][j]=f[i-1][q[1]]+abs(a[i]-b[j]);
        }
      }
    ans=inf;
    For(i,1,m)
    ans=min(ans,f[n][i]);
    For(i,1,n)
      For(j,1,n)
        f[i][j]=0;
    For(i,1,n)
      {
          r=0;
          For(j,1,m)
        {
            while(l<=r&&f[i-1][j]>=f[i-1][q[r]])r--;
            q[++r]=j;
            f[i][j]=f[i-1][q[1]]+abs(a[i]-b[m]);
        }
      }
    ans=min(ans,f[n][m]);
    o(ans);
     return 0;
}

 

 

 

考场贪心骗分代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<queue>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<ctime>
  7 #include<cstring>
  8 #define inf 2147483647
  9 #define For(i,a,b) for(register int i=a;i<=b;i++)
 10 #define p(a) putchar(a)
 11 #define g() getchar()
 12 //by war
 13 //2017.10.18
 14 using namespace std;
 15 int n;
 16 int Max;
 17 int last;
 18 int a[2010];
 19 int d[2010];
 20 bool b[2010];
 21 int p[2010];
 22 int f[2010];
 23 int ans[5];
 24 void in(int &x)
 25 {
 26     int y=1;
 27     char c=g();x=0;
 28     while(c<'0'||c>'9')
 29     {
 30     if(c=='-')
 31     y=-1;
 32     c=g();
 33     }
 34     while(c<='9'&&c>='0')x=x*10+c-'0',c=g();
 35     x*=y;
 36 }
 37 void o(int x)
 38 {
 39     if(x<0)
 40     {
 41         p('-');
 42         x=-x;
 43     }
 44     if(x>9)o(x/10);
 45     p(x%10+'0');
 46 }
 47 
 48 void LIS()
 49 {
 50     For(i,1,n)
 51     f[i]=1,d[i]=0;
 52     For(i,1,n)
 53       {
 54           For(j,1,i-1)
 55         {
 56             if(a[j]<=a[i])
 57             {
 58                 if(f[j]+1>f[i])
 59                 {
 60                     f[i]=f[j]+1;
 61                     d[i]=j;
 62                 }
 63             }
 64         }
 65         if(Max<f[i])
 66         {
 67             Max=f[i];
 68             last=i;
 69         }
 70       }
 71       int ft;
 72       for(ft=last;d[ft]!=0;ft=d[ft])
 73       b[ft]=true;
 74       for(int i=ft-1;i>=1;i--)
 75       {
 76           ans[0]+=abs(p[i]-p[i+1]);
 77           p[i]=p[i+1];
 78       }
 79       For(i,ft+1,n)
 80       if(!b[i])
 81       {
 82           ans[0]+=abs(p[i]-p[i-1]);
 83           p[i]=p[i-1];
 84       }
 85 }
 86 
 87 void LRS()
 88 {
 89     Max=0;
 90     For(i,1,n)
 91     f[i]=1,b[i]=false,d[i]=0;
 92     For(i,1,n)
 93       {
 94           For(j,1,i-1)
 95         {
 96             if(a[j]>=a[i])
 97             {
 98                 if(f[j]+1>f[i])
 99                 {
100                     f[i]=f[j]+1;
101                     d[i]=j;
102                 }
103             }
104         }
105         if(Max<f[i])
106         {
107             Max=f[i];
108             last=i;
109         }
110       }
111       int ft;
112       for(ft=last;d[ft]!=0;ft=d[ft])
113       b[ft]=true;
114       for(int i=ft-1;i>=1;i--)
115       {
116           ans[1]+=abs(p[i]-p[i+1]);
117           p[i]=p[i+1];
118       }
119       For(i,ft+1,n)
120       if(!b[i])
121       {
122           ans[1]+=abs(p[i]-p[i-1]);
123           p[i]=p[i-1];
124       }
125 }
126 
127 int main()
128 {
129 //    freopen("grading.in","r",stdin);
130 //    freopen("grading.out","w",stdout);
131     in(n);
132     For(i,1,n)
133     in(a[i]),p[i]=a[i];
134     LIS();
135     For(i,1,n)
136     p[i]=a[i];
137     LRS();
138     o(min(ans[0],ans[1]));
139      return 0;
140 }
View Code

 

posted @ 2017-10-18 18:00  WeiAR  阅读(348)  评论(2编辑  收藏  举报