USACO 2006 Mar SkiLift

来源:互联网 发布:点位图软件 brd 编辑:程序博客网 时间:2024/04/30 22:37
首先定义dp[i]为从1到i 最小的柱子数(i 也必须有柱子),我们还是用刷表法……(根本不会填表)

dp[i] 可以刷到的区域为[i+1,i+l],而且也要满足题意,即缆线不能触碰山,即Hi与Hi+j连线不能与山接触,所以我们在向前for的同时记录现在需要的最小斜率(有坑),然后判断此时斜率是否大于这个斜率就好了.

之前说斜率有坑是因为斜率的范围是[-1e9,1e9],然而又会有小数,为了精度的问题,难受的我又放出了些奇怪的东西(Fra),然后在错了两次之后A了

#include<cstdio>#include<cstring>#include<cstdlib>#define M 5005int H[M],dp[M];void check(int &x,int y){    if(x==-1||x>y)x=y;}int gcd(int a,int b){    return b==0?a:gcd(b,a%b);}struct Fra{    int son,mom;    void cl(){        int ll=gcd(abs(son),abs(mom));        son/=ll,mom/=ll;    }    bool operator <(const Fra &a)const{        return 1LL*son*a.mom<1LL*a.son*mom;    }};Fra max(Fra x,Fra y){    return x<y?y:x;}int main(){    int n,k;    scanf("%d %d",&n,&k);    for(int i=1;i<=n;i++)scanf("%d",&H[i]);    memset(dp,-1,sizeof(dp));    dp[1]=1;    for(int i=1;i<=n;i++)        if(dp[i]!=-1){            Fra now=(Fra){-1e9-5,1};            for(int l=1;l<=k&&i+l<=n;l++){                Fra ll=(Fra){H[i+l]-H[i],l};                now=max(now,ll);                if(!(ll<now))check(dp[i+l],dp[i]+1);            }        }    printf("%d\n",dp[n]);    return 0;}


0 0