*POJ3666.Making the Grade(DP+离散化)

题目链接:http://poj.org/problem?id=3666
题意:求将一个序列调整成纯单调(可以相等)的序列所需要的最小代价
解题思路:
分两种情况讨论:
①不减序列:dp[i][j]表示前0~i个数的最大值为这i个数中第j大值需要改变的量
因为序列a[i]的最大值可能达到1e9的大小,所以需要用用到离散化,将序列a从小到大顺序放在数组b中,j表示a序列中第j大的数值
转移方程为 dp[i][j]=abs(a[i]-b[j])+min(dp[i-1][k]),1<=k<=j,
对于min(dp[i-1][k])的求法不需要遍历,只需要在j推进过程中不断更新即可

ll solveup(){    //上升序列
	ll minv;
	ll ans;
	for(int i=1;i<=n;i++)
		dp[1][i]=abs(a[1]-b[i]);
	for(int i=2;i<=n;i++){
		minv=dp[i-1][1];
		for(int j=1;j<=n;j++){
			minv=min(minv,dp[i-1][j]);
			dp[i][j]=abs(a[i]-b[j])+minv;
		}
	}
	ans=dp[n][1];
	for(int i=1;i<=n;i++)
		ans=min(ans,dp[n][i]);
	return ans;
}

②不增序列:dp[i][j]表示前0~i个数的最大值为这i个数中第j小值需要改变的量
a序列按从大到小顺序保存在b数组中,其他同理

ll solvedown(){
	ll minv;
	ll ans;
	for(int i=1;i<=n;i++)
		dp[1][i]=abs(a[1]-b[i]);
	for(int i=2;i<=n;i++){
		minv=dp[i-1][1];
		for(int j=1;j<=n;j++){
			minv=min(minv,dp[i-1][j]);
			dp[i][j]=abs(a[i]-b[j])+minv;
		}
	}
	ans=dp[n][1];
	for(int i=1;i<=n;i++)
		ans=min(ans,dp[n][i]);
	return ans;
}
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define ll long long
int n;
ll a[2200];
ll b[2200];
ll dp[2200][2200];  //前0~i个数的最大值为这i个数中第j大值需要改变的量
                    //前0~i个数的最大值为这i个数中第j小值需要改变的量
bool cmp(int a,int b){
	return a>b;
}
ll solveup(){    //上升序列
	ll minv;
	ll ans;
	for(int i=1;i<=n;i++)
		dp[1][i]=abs(a[1]-b[i]);
	for(int i=2;i<=n;i++){
		minv=dp[i-1][1];
		for(int j=1;j<=n;j++){
			minv=min(minv,dp[i-1][j]);
			dp[i][j]=abs(a[i]-b[j])+minv;
		}
	}
	ans=dp[n][1];
	for(int i=1;i<=n;i++)
		ans=min(ans,dp[n][i]);
	return ans;
}
ll solvedown(){
	ll minv;
	ll ans;
	for(int i=1;i<=n;i++)
		dp[1][i]=abs(a[1]-b[i]);
	for(int i=2;i<=n;i++){
		minv=dp[i-1][1];
		for(int j=1;j<=n;j++){
			minv=min(minv,dp[i-1][j]);
			dp[i][j]=abs(a[i]-b[j])+minv;
		}
	}
	ans=dp[n][1];
	for(int i=1;i<=n;i++)
		ans=min(ans,dp[n][i]);
	return ans;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+1+n);
	int ans1=solveup();
	sort(b+1,b+1+n,cmp);
	int ans2=solvedown();
	cout<<min(ans1,ans2)<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/107235458