POJ 3666-Making the Grade (DP+离散化)

问题链接:https://cn.vjudge.net/contest/173831#problem/P

题意:给你n个数,为你将其变为不增或不减序列所花费的最小成本(花费的规则见题面)

这道题的题目数据有问题,只用求个递增就可以了,其实递减也是一样的。

问题是怎么求,求最长上升子序列肯定是不对的(虽然我一看是一直是这样想的),为什么不对呢

因为你求完最长的上升子序列的时候,保留的元素都已经固定了,呢假如删除的元素花费更大,

保留的元素如果删除的话成本更小呢?这样的话答案不就不是最优的吗。

呢就只能换一种DP方式了,后来想到了一种,其实和正解已经差不多了,在我意识到最长上升子序列

不对的之后,觉得可以用DP【i】【j】表示前i个数,最大值为j的最小花费,感觉这样一定对。

但是看了看数据范围---1000000000,这我搞毛线啊,数组都开不了,好吧,只能离散化了


#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
using namespace std;  
typedef long long  ll;  
#define inf 1000000000  
#define mod 1000000007   
#define  maxn  2005
#define  lowbit(x) (x&-x)  
#define  eps 1e-10  
ll dp[maxn][maxn],a[maxn],b[maxn];
ll abss(ll a)
{
	if(a<0)
		return -a;
	return a;
}
int main(void)
{
	ll n,i,j,ans;
	while(scanf("%lld",&n)!=EOF)
	{
		ans=inf;
		memset(dp,0,sizeof(dp));
		for(i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
			b[i]=a[i];
		}
		sort(b+1,b+n+1);
		for(i=1;i<=n;i++)
		{
			ll tmp=dp[i-1][1];
			for(j=1;j<=n;j++)	
			{
				tmp=min(tmp,dp[i-1][j]);
				dp[i][j]=abss(a[i]-b[j])+tmp;
			}
		}
		for(i=1;i<=n;i++)
			ans=min(ans,dp[n][i]);
		printf("%lld\n",ans);
	}
	return 0;
}



你可能感兴趣的:(DP)