You Are the One HDU - 4283 区间dp

本文探讨了一种使用区间动态规划方法来解决特定排队问题的算法。该问题涉及一组表演者,每个人上台的顺序会影响其不愉快度。通过栈操作调整上台顺序,目标是最小化所有人的总不愉快度。文章详细解释了区间DP的思路和转移方程,并提供了AC代码实现。

题解

题目大意,一队人排队上台表演,每个人有个值a[i],他第k个上场就会有a[i]*(k-1)的不愉快度,现在有个栈可以调整上台顺序,对于每个人可以选择进栈或者直接上台,在栈中的人可以随时上台,问不愉快度的最小总和

区间dp求解,d[i][j]表示区间[i, j]第i个前面没有人的情况下的最小代价,也就是只有区间[i, j]这些人任意安排顺序上场的最小代价
对于每个区间考虑将第一个人进栈,等后面的人都走了之后再出栈上台,转移为d[i][j]=min(d[i][j], d[i+1][j] + a[i] * (j - i))
a[i] * (j - i)是因为他要最后上场,额外的不愉快度为a[i]*(区间长度-1),由于转移的区间是内部的区间所以不会出现交叉进栈的情况
合并区间时枚举区间间断点k,转移为d[i][j] = min(d[i][j], d[i][k] + d[k + 1][j] + (k - i + 1) * (s[j] - s[k]))利用前缀和将后区间额外的不愉快度计算出来

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 110;
int a[MAXN], s[MAXN];
int d[MAXN][MAXN]; //区间[i, j]第i个前面没有人的情况下的最小代价

int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	for (int ti = 1; ti <= T; ti++)
	{
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]), s[i] = s[i - 1] + a[i]; //前缀和
		memset(d, 0x3f, sizeof(d));
		for (int i = 1; i <= n; i++) d[i][i] = 0; //单个人为0
		for (int l = 1; l < n; l++)
			for (int i = 1; i + l <= n; i++)
			{
				int j = i + l;
				d[i][j] = min(d[i][j], d[i + 1][j] + a[i] * (j - i)); //尝试把第i个人进栈先让[i+1, j]上场
				for (int k = i; k < j; k++)
					d[i][j] = min(d[i][j], d[i][k] + d[k + 1][j] + (k - i + 1) * (s[j] - s[k]));
			}
		printf("Case #%d: ", ti);
		cout << d[1][n] << endl;
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值