HDU-2770-Easy Climb

来源:互联网 发布:粤知一二中的女孩猫猫 编辑:程序博客网 时间:2024/06/05 08:12

题意:这个题是给你一个序列,然后你对于首尾2个值不能改动,其他的值你可以改动,要求你通过修改使得相邻2个值之差绝对值不超过d,然后修改的代价为修改后的值域原来值差的绝对值之和。

思路:其实白书上面说了一些思路的(新版的小白书),不得不佩服上面提到的修改后的状态必然为hi+kd(1<=i<=n,-n<k<n)这样就转为n^2了,可以用dp[i][x]表示当前为i,状态为x满足题意的最少代价,则转移方程式为dp[i][x]=abs(h[i]-x)+min(dp[i-1][y]( x-d<=y<=x+d),还需要注意的是这个题需要离散化,然后需要各种long long

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const long long inf=1LL<<62;const int maxn=110;const int maxm=maxn*maxn*2;int n,cnt;long long h[maxn],s[maxm],dp[maxn][maxm],d;int q[maxm];void Init(){    for(int i=0;i<=n;i++)        for(int j=0;j<cnt;j++)            dp[i][j]=inf;}void solve(){    Init();    int ind=lower_bound(s,s+cnt,h[1])-s;    dp[1][ind]=0;    for(int i=2;i<=n;i++)    {        int pre=0,last=0,now=0;        for(int j=0;j<cnt;j++)        {            while(now<cnt&&s[now]<=s[j]+d)            {                while(pre<last&&dp[i-1][q[last-1]]>=dp[i-1][now])                    last--;                q[last++]=now++;            }            while(pre<last&&s[j]-d>s[q[pre]])                pre++;            dp[i][j]=abs(h[i]-s[j])+dp[i-1][q[pre]];        }    }    ind=lower_bound(s,s+cnt,h[n])-s;    if(dp[n][ind]>=inf)        printf("impossible\n");    else        printf("%I64d\n",dp[n][ind]);}int main(){    int T;    scanf("%d",&T);    while(T--)    {        cnt=0;        scanf("%d%I64d",&n,&d);        for(int i=1;i<=n;i++)            scanf("%I64d",&h[i]);        for(int i=1;i<=n;i++)            for(long long j=0;j<n;j++)            {                s[cnt++]=h[i]-j*d;                s[cnt++]=h[i]+j*d;            }        sort(s,s+cnt);        cnt=unique(s,s+cnt)-s;        solve();    }    return 0;}


0 0
原创粉丝点击