将一个序列调整为单调序列的最小代价问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将一个序列调整为单调序列的最小代价问题相关的知识,希望对你有一定的参考价值。

给出一个长度最多达到3000的整数序列,我们可以改变这个序列的任意一个元素的值。对于这些改变,我们记下每次改变的代价,即改变后的元素值与改变前的元素值的差值的绝对值。每次改变的代价的总和就是调整的总代价。要求在代价最小的情况下,将序列调整成为一个单调的序列(单调性可以不严格,并且单调递增和单调递减均可)。那么,应该使用怎样的算法?
我觉得这是数学的内容啊...

个人觉得可以用取中值的办法:

代价最小,那就是要尽量顺着原序列。
平均分两部分,比较前后1500个数的均数,如果前面的比较大,那就调成递减,否则相反;
平均分四部分,以各自的均值为基准,再比较前后750个的均值。

依此类推。
参考技术A 回溯 贪心 动态规划
没有时限你还可以 递归模拟。。。

我觉得这是数学的内容啊...
题目最后都问你 应该使用怎样的算法了 肯定是计算机算法题 就是用回溯 贪心法 和动态规划
虽说数学与计算机有密切关系,但数学指提供个大致思路,配合计算机强大的计算功能模拟和典型的计算机算法,能很好的解决问题。
参考技术B 问错地方了吧,应该到电脑区去问。 参考技术C 具体问题回答.

bzoj1345[Baltic2007]序列问题Sequence 单调栈

题目描述

对于一个给定的序列a1, …, an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和ai+1用一个元素max(ai,ai+1)替代,这样得到一个比原来序列短的新序列。这一操作的代价是max(ai,ai+1)。进行n-1次该操作后,可以得到一个长度为1的序列。我们的任务是计算代价最小的reduce操作步骤,将给定的序列变成长度为1的序列。

输入

第一行为一个整数n( 1 <= n <= 1,000,000 ),表示给定序列的长度。接下来的n行,每行一个整数ai(0 <=ai<= 1, 000, 000, 000),为序列中的元素。

输出

只有一行,为一个整数,即将序列变成一个元素的最小代价。

样例输入

3
1
2
3

样例输出

5


题解

单调栈

本题卡set。。。

通过观察可以知道最优策略下,非最大值的数,一定是与它左右第一个比它大的数中较小的那个替代的。

那么就可以使用单调栈扫出每个位置左右第一个比它大的数,然后计算即可。

#include <cstdio>
#include <algorithm>
#define N 1000010
using namespace std;
int a[N] , v[N] , sta[N] , top;
int main()
{
	int n , i;
	long long ans = 0;
	scanf("%d" , &n);
	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
	a[0] = a[n + 1] = 1 << 30 , top = 1;
	for(i = 1 ; i <= n ; i ++ )
	{
		while(a[i] > a[sta[top]]) top -- ;
		v[i] = a[sta[top]] , sta[++top] = i;
	}
	top = 1 , sta[1] = n + 1;
	for(i = n ; i ; i -- )
	{
		while(a[i] >= a[sta[top]]) top -- ;
		v[i] = min(v[i] , a[sta[top]]) , sta[++top] = i;
		if(v[i] != 1 << 30) ans += v[i];
	}
	printf("%lld\n" , ans);
	return 0;
}

 

 

以上是关于将一个序列调整为单调序列的最小代价问题的主要内容,如果未能解决你的问题,请参考以下文章

Making the Grade [POJ3666] [DP]

POJ 3666 Making the Grade [DP]

BZOJ1345[Baltic2007]序列问题Sequence 贪心+单调栈

bzoj1345[Baltic2007]序列问题Sequence*

括号序列的最小代价

序列排序