【DP周】- 第一周(基础DP) - day4 - Making the Grade

Making the Grade
在这里插入图片描述

分析:
要想找到最低成本那么处理过后的上升或者下降的序列一定是原序列中的值
那么这样
我们就可以先将原序列排好序得到字符串b
现在原字符串中的元素的状态就是在字符串b中第1~n一共n中状态
所以
我们可以列出状态转移方程
表示前i个元素在字符串b中位置为j时的最低成本
那么在找前i个元素在j位置时的最低成本的前提下,要找到前i - 1个元素在什么位置有最低成本
v = f[i - 1][1]
v = max(v, f[i - 1][j])
之后再加上a[i] 到 b[i] 的花费即f[i][j]
dp[i][j] = abs(a[i] - b[j]) + v
注意
abs只适用于int类型,定义的longlong要自己定义个abs函数,否则会编译错误(别问我是怎么知道的)
最后
上面描述的时上升序列,下降序列只有排序的时候不同。

#include <iostream>
#include <algorithm>
 
#define ll long long
#define Abs(a) ((a) > 0 ? (a) : -(a))
using namespace std;

const int N = 2021;
int n;
ll a[N];
ll b[N];
ll dp[N][N];


bool cmp(ll a, ll b)
{
	return a > b;
}
ll up()
{
	sort(b + 1, b + n + 1);	
	
	for(int i = 1; i <= n; i ++)
	{
		ll v = dp[i - 1][1]; // 前i - 1个序列位置在b序列的1处的最小cost 
		
//		cout << v << "**" <<endl;
		for(int j = 1; j <= n; j ++)
		{
			v = min(v, dp[i - 1][j]);
			dp[i][j] = Abs(a[i] - b[j]) + v;
		}	
	}
	ll ans = dp[n][1];
	for(int i = 1; i <= n; i ++)
		ans = min(ans, dp[n][i]);
	
	return ans; 
} 
ll down()
{
	sort(b + 1, b + n + 1, cmp);
	for(int i = 1; i <= n; i ++)
	{
		ll v = dp[i - 1][1]; // 前i - 1个序列位置在b序列的0处的最小cost 
		for(int j = 1; j <= n; j ++)
		{
			v = min(v, dp[i - 1][j]);
			dp[i][j] = Abs(a[i] - b[j]) + v;
		}	
	}
	ll 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 ++)
		cin >> a[i], b[i] = a[i]; // 离散化 将a的值缩小在n的范围内 
		
	cout << min(up(), down()) << endl;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值