POJ 3666 Making the Grade

来源:互联网 发布:安卓电子白板书写软件 编辑:程序博客网 时间:2024/06/10 16:08
/*基础dp
Making the Grade
题意: 给出n个数字组成序列a,然后再找到一个序列b,从1至n,abs(a[i]-b[i])的总和最小,其中序列b是非严格单调序列,要么是要么是非递减序列,要么是非递增序列。题解:分别求非严格递减和非严格递减的答案,取最小值怎么求? 非严格递增:如果数组数字需要改变,那么往目前数组最大的数字变将数组排序存于c[];dp[i][j]代表取第i个数,现在集合最后的数是排序后的数组的第j个dp[i][j] = min(dp[i-1][k])(1<=k<=j)+abs(a[i]-c[j])*/#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<queue>#include<stack>#include<map>using namespace std;const int INF = 0x3f3f3f3f;const int N = 2010;int dp[N];int n;int slove(int* now,int* num){ memset(dp,0,sizeof(dp)); for(int i = 0; i < n; i++) { int mn = INF; for(int j = 0; j < n; j++) { mn = min(mn,dp[j]); //取上个状态 1~j 的最小 dp[j] = mn+abs(now[i]-num[j]); //printf("%d %d ",num[j],dp[j]); } } int ans = INF; for(int i = 0; i < n; i++) ans = min(ans,dp[i]); return ans;}int a[N],b[N],c[N];int main(){ cin >> n; for(int i = 0; i < n; i++) { cin >> a[i]; b[n-i-1] = a[i]; c[i] = a[i]; } sort(c,c+n); printf("%d\n",min(slove(a,c),slove(b,c))); return 0;}

0 0