[R19D]构造序列

dp[i]表示到数列第i位的最小花费,那么他要么是从前面K个相同数字发展而来的,要么是前面K个连续递增数字发展而来的。 要么就是增加的单个数字的花费而来的。
但是复杂度应该是N^2 ,比赛时候感觉会超时的,结果居然可以ac

// 112. [R19D]构造序列.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
[R19D]构造序列
原题地址:https://bs.daimayuan.top/p/112
题目描述
apiadu 有一个初始为空的序列,他需要通过两种神奇的操作来构造出目标序列 c:
批量添加:选定任意非负整数 k,x,可以一次性在序列末尾添加 k 个相同的数字 x,执行这个操作的所需金币为 A。
连续添加:选定任意非负整数 k,x,可以一次性在序列末尾添加 k 个从 x 开始的连续的数字,(即 x, x+1, ..., x+k-1)。执行这个操作的所需金币为 B。
请你帮助 apiadu 计算出,构造出给定的目标序列所需的最少金币数量。
输入格式
第一行包含三个整数 n,A,B,分别表示目标序列的长度,操作 1 的金币数,操作 2 的金币数。
第二行包含 n 个整数 ci,表示目标序列。
输出格式
输出一个整数,表示构造目标序列所需的最少金币数量。
样例输入
5 3 2
1 1 2 3 4
样例输出
4
样例解释
第一次操作:使用操作 2(其中 k=1,x=1),添加 1 个 1,此时序列为 [1],花费 2 个金币。
第二次操作:使用操作 2(其中 k=4,x=1),此时序列为 [1,1,2,3,4],花费 2 个金币。
总的花费数量为 2+2 = 4 个金币。
数据范围与提示
对于 50% 的数据,1 <= n <= 1000。
对于 100% 的数据,1 <= n <= 10^6,1 <= A,B,ci <= 10^9。
*/


#include <iostream>
#include <cstring>


using namespace std;

const int N = 1000010;
long long dp[N], arr[N];
int n; int A, B;

int main()
{
	cin >> n >> A >> B;
	memset(dp, 0x3f, sizeof dp);
	for (int i = 1; i <= n; i++) cin >> arr[i];
	arr[0] = -1;	dp[0] = 0;
	for (int i = 1; i <= n; i++) {
		int curr = arr[i];
		for (int j = i - 1; j >= 0; j--) {
			if (curr != arr[j]) {
				dp[i] = min(dp[i], dp[j] + A);
				break;
			}
		}
		for (int j = i - 1; j >= 0; j--) {
			if (curr != arr[j] + 1) {
				dp[i] = min(dp[i], dp[j] + B);
				break;
			}
			else {	curr = arr[j];}
		}
		dp[i] = min(dp[i], dp[i - 1] + min(A, B));
	}

	cout << dp[n] << endl;

	return 0;
}
 

posted on 2025-07-10 10:18  itdef  阅读(8)  评论(0)    收藏  举报

导航