题目链接;
HDU 4283 You Are the One
题意:
【非诚勿扰?】
有
n
个人需要上台,每个人的初始diaosi值(题目就这么说的)是
数据范围:
n≤100,data[i]∈[0,100]
分析:
区间
dp
这种
dp
受制于状态转移过程一般的复杂度都是
O(n3)
,并且第一层循环一般都是倒着递推。
其主要难点也许在于如何确定状态转移,更具体的说,就是确定循环枚举的第三层的
k
的含义。一般都是指区间中的第
但是这道题,我们首先可以把小黑屋看成一个栈,如果我们枚举区间第
k
个人是第一个上场的话,我们仍然不知道左右区间每个人的上场顺序,这样子左右区间就不是完全独立的了,不具备无后效性这个特点。
我们可以枚举第
对于子区间
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N = 110;
const int inf = 0x7fffffff;
int T, n, cases = 0;
ll data[MAX_N], sum[MAX_N], dp[MAX_N][MAX_N];
int main()
{
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
sum[0] = 0;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &data[i]);
sum[i] = sum[i - 1] + data[i];
}
for (int i = 0; i <= n; ++i) {
for (int j = 0; j <= n; ++j) {
if (i < j) dp[i][j] = inf;
else dp[i][j] = 0;
}
}
for (int i = n; i >= 1; --i) {
for (int j = i + 1; j <= n; ++j) {
for (int k = 1; k <= j - i + 1; ++k) {
dp[i][j] = min(dp[i][j], data[i] * (k - 1) + dp[i + 1][i + k - 1] + dp[i + k][j] + k * (sum[j] - sum[i + k - 1]));
}
}
}
printf("Case #%d: %lld\n", ++cases, dp[1][n]);
}
return 0;
}

本文解析了HDU4283 YouAretheOne问题,通过使用区间动态规划方法解决了一个关于上场顺序和最小化总愤怒值的问题。文章详细介绍了状态转移方程的设计思路及实现细节。

582

被折叠的 条评论
为什么被折叠?



