A celestial scroll, detailing Zeus’s latest whim unfurls before Hermes: the next few millenia will be a period of divine gifting for mortals. Hermes, the messenger god, is tasked with delivering these gifts. Not just any gifts, mind you, but exquisitely crafted items from the Olympian workshops: a lyre that plays melodies of pure joy, a quill that writes words of profound wisdom, and so on. Each of the N N N gifts is unique, and, to complicate matters, each has an optimal delivery date, a day when its magic would be most potent. But a divine law forbids delivering gifts before their optimal delivery day, lest mortals become complacent and entitled. Of course, all gifts must be delivered.
Adding to the challenge, Hermes, despite being the fastest god on Olympus, is always extremely busy. Between managing the celestial postal service and refereeing chariot races, he knows that he can only dedicate at most K K K days for the deliveries (each of those days, Hermes can deliver any number of gifts). Furthermore, late deliveries incur penalties: for each gift, the penalty is the square of the difference between its actual delivery day and its optimal delivery day. If a lyre is delivered a day or two late, a village might experience a few hours of slightly off-key music. A minor inconvenience, to be sure. However, if the lyre is delivered a month or a year late, the consequences are far more dire: a full year of discordant melodies, enough to drive even the most stoic musician to madness. The potential for chaos is immense.
And this is where you come in, mortal friend. Hermes, with his myriad responsibilities, could use a helping hand. Can you help him plan his divine calendar by determining the best days for delivering the gifts, so as to minimize the sum of late delivery penalties?
Input
On the first line of the input, two space-separated integers:
On the second line, N N N space-separated integers d i d_{i} di, representing the optimal delivery date of each gift.
Output
A single line of space-separated integers, where the i i i-th element is the day when Hermes should deliver the i i i-th gift. If there are multiple optimal solutions, they will all be accepted.
Limits
Example
Input
5 2
50 0 51 10 50
Output
51 10 51 10 51
宙斯决定在接下来的几千年里为凡人分发礼物。赫尔墨斯(Hermes)被指派负责分发这些礼物。每个礼物都有一个最佳的交付日期,且不能在最佳日期之前交付。赫尔墨斯最多只能使用 K K K 天来分发所有礼物。如果礼物在最佳日期之后交付,会产生惩罚,惩罚值为实际交付日期与最佳交付日期之差的平方。目标是找到一种分发礼物的方案,使得总惩罚最小。
问题分析:
关键思路:
复杂度:
输入处理:
预处理:
动态规划:
回溯:
#include
using namespace std;
#define int long long int
#define endl '\n'
#define close ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 5000 + 10;
const int inf = 1e18;
vector<vector<int>> dp(N, vector<int>(25, inf));
int n, K;
vector<int> v(N);
int cmp(int x, int y)
{
return x > y;
}
int sum[N][N];
void dodo()
{
for (int r = n; r >= 1; --r)
{
for (int l = r; l >= 1; --l)
{
sum[l][r] = sum[l + 1][r] + abs((v[r] - v[l]) * (v[r] - v[l]));
}
}
}
signed main()
{
close;
cin >> n >> K;
// K = min(K, n);
for (int i = 1; i <= n; ++i)
{
cin >> v[i];
}
vector<pair<int, int>> s(n + 1);
for (int i = 1; i <= n; i++)
s[i].first = v[i], s[i].second = i;
sort(s.begin() + 1, s.begin() + 1 + n);
sort(v.begin() + 1, v.begin() + n + 1);
dodo();
// for (int r = n; r >= 1; --r)
// {
// for (int l = r; l >= 1; --l)
// {
// cout << l << ' ' << r << ' ' << sum[l][r] << endl;
// }
// }
dp[0][0] = 0;
for (int i = 1; i <= n; ++i)
{
for (int j = 0; j < i; ++j)
{
for (int k = K; k >= 1; --k)
{
dp[i][k] = min(dp[i][k], dp[j][k - 1] + sum[j + 1][i]);
}
}
}
// cout << dp[n][K];
// for (int i = 1; i <= n; ++i)
// {
// for (int j = 1; j <= K; ++j)
// {
// cout << dp[i][j] << ' ';
// }
// cout << endl;
// }
vector<int> an;
an.push_back(n);
array<int, 3> now;
now = {n, min(n, K), dp[n][min(n, K)]};
for (int i = K; i >= 1; i--)
{
for (int j = 1; j <= now[0]; j++)
{
if (now[2] - dp[j][i - 1] == sum[j + 1][now[0]])
{
now[0] = j, now[1]--, now[2] = dp[j][i-1];
an.push_back(j);
break;
}
}
}
reverse(an.begin(), an.end());
// for (auto it : an)
// {
// cerr << it << ' ';
// }
//cout << endl;
int no = 0;
vector<int> ans(n + 10);
for (int i = 1; i <= n; i++)
{
if (i <= an[no])
ans[s[i].second] = v[an[no]];
if (i == an[no])
no++;
}
for (int i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
}
这道题目通过动态规划的方法,解决了在有限天数内分发礼物并最小化惩罚的问题。关键在于如何定义状态转移方程,并通过预处理来优化计算。最终的代码实现了这一思路,并通过回溯找到最优的分发方案。