Codeforces Round #371 (Div. 1) C. Sonya and Problem Wihtout a Legend(DP+思维)

题目链接
在这里插入图片描述
题意:给定一个初始数组,你每次操作可以选择数组中的一个数进行加1或者减1操作,问你最少要多少操作使得数组变成严格单调。
思路:感觉这个题思路完全想不到,我们将初始数组都执行a【i】=a【i】-i操作,然后我们思考一下这个修改成这样会有什么好处,修改后如果存在方案使得数组所有数都等于x(假设为x),那么我们最终答案的最小操作是不是就是等于a【i】变成x的步数累加起来?于是我们就可以枚举要变成那个数,最后取最小值就行了。
想得到的话倒是挺简单的,想不到的话就呵呵了QAQ

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e3+1;
ll dp[maxn][maxn],a[maxn],b[maxn];
map<ll,ll>p;
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%lld",&a[i]),a[i]-=i,b[i]=a[i];
	sort(b+1,b+1+n);
	for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) dp[i][j]=1e18;
	for(int i=1;i<=n;++i)
	{
		ll minn=1e18;
		for(int j=1;j<=n;++j)
		{
			minn=min(minn,dp[i-1][j]);
			dp[i][j]=minn+abs(a[i]-b[j]);
		}
	}
	ll ans=1e18;
	for(int i=1;i<=n;++i) ans=min(ans,dp[n][i]);//最后看一下变成那个数花费最小
	printf("%lld\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值