codeforces 713C(Round #371 Div2 E) Sonya and Problem Wihtout a Legend Dp + 前缀 +离散化

来源:互联网 发布:吴京的地位知乎 编辑:程序博客网 时间:2024/05/21 19:22
/*    题目描述:给出一个包含n个数的序列a1,a2,...,an,先要把该序列修改成严格单增的序列,假设修改成                    b1,b2,...,bn的花费为 |a1 - b1|+|a2 - b2|+...+|an - bn|,问最小花费是多少?    方法:非常类似于POJ3666,建议先把这道题AC,为了转化成POJ3666,需对性质进行如下分析:              严格递增的含义是a[j] - a[i] >= j - i , 变形得a[j] - j >= a[i] - i , 即数列x[i] = a[i] - i非严格              单调递增; 因此 , 在输入时得到初始的数组x[i] (x[i] = a[i] - i ) ,现要求将数组x[i]变成非严              格单调递增的最小花费,也就是POJ3666中的问题*/#pragma warning(disable:4786)#pragma comment(linker, "/STACK:102400000,102400000")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#include<queue>#include<map>#include<set>#include<vector>#include<cmath>#include<string>#include<sstream>#define LL long long#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)#define mem(a,x) memset(a,x,sizeof(a))#define lson l,m,x<<1#define rson m+1,r,x<<1|1using namespace std;const LL INF = 1e15;const int mod = 1e9 + 7;const double PI = acos(-1.0);const double eps=1e-6;const int maxn = 3000 + 5 ;LL dp[maxn][maxn] ;LL a[maxn] , b[maxn] , prefix[maxn];int main(){    int n ;    scanf("%d",&n);    for(int i = 1 ; i<= n ; i++){        scanf("%lld",&a[i]);        a[i] = a[i] - i ;        b[i] = a[i] ;    }    sort( b + 1 , b + n + 1 );    for(int i = 1  ; i<= n ; i++){        prefix[i] = 0;        for(int j = 1 ; j<= n ; j++){            dp[i][j] = INF;        }    }    int len = unique(b + 1 , b + n + 1 ) - b - 1 ;    for(int i = 1 ; i <= n ; i++){        for(int j =1 ; j <= len ; j++){            dp[i][j] = min(dp[i][j] , prefix[j ] + abs(a[i] - b[j]) ) ;        }        prefix[1] = dp[i][1] ;        for(int j = 2 ; j<= len ; j++){            prefix[j] = min(prefix[j - 1] , dp[i][j]) ;  //第i次循环中prefix[j]表示dp[i][k](k<=j)的最小值,用于第i+1次循环时dp[i+1][j]的更新        }    }    LL ans = INF ;    for(int i = 1 ; i<= len ; i++){        ans = min(ans , dp[n][i]);    }    printf("%lld\n",ans);    return 0;}

0 0
原创粉丝点击