思路:记忆dp,用前一个月的所有可取状态更新后一个月的所有可取状态,结果是最后一个月的所有可取状态的最小值(可取状态即雇佣worker数>=所需worker数)
#include<iostream>
#include<vector>
#include<algorithm>
#include<utility>
using namespace std;
vector<int> wn; //worker_need:每一个月所需的worker数
vector<int> swn; //sorted_worker_need:排序后的各个月份所需worker数
vector<int> dir; //wn到swn的映射,即wn中的数在swn中对应的位置
int cost[3]; //三种费用
vector<int> dp[13]; //dp表,最多12个月
//额外费用计算函数,swn[j]:当前所需worker数,swn[k]:子状态雇佣worker数
int mag(int j, int k)
{
if (swn[j] > swn[k])
return (swn[j] - swn[k])*cost[0];
if (swn[j] < swn[k])
return (swn[k] - swn[j])*cost[2];
return 0;
}
//dp
void solve(int n)
{
for (int i = 0; i < n; i++)
dp[i].clear();
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
dp[i].push_back(999999);
for (int i = dir[0]; i < n; i++)
dp[0][i] = (cost[0] + cost[1])*swn[i];
for (int i = 1; i < n; i++)
{
for (int j = dir[i]; j < n; j++)
{
for (int k = dir[i - 1]; k < n; k++)
{
dp[i][j] = min(dp[i][j], dp[i - 1][k] + mag(j, k) + cost[1] * swn[j]);
}
}
}
}
int main()
{
int n;
while (cin >> n&&n)
{
for (int i = 0; i < 3; i++)
cin >> cost[i];
wn.clear();
swn.clear();
for (int i = 0; i < n; i++)
{
int twn;
cin >> twn;
wn.push_back(twn);
swn.push_back(twn);
}
sort(swn.begin(), swn.end());
dir.clear();
for (int i = 0; i < n; i++)
{
dir.push_back(lower_bound(swn.begin(), swn.end(), wn[i])-swn.begin());
}
solve(n);
int ans= 999999;
for (int i = dir[n-1]; i < n; i++)
{
ans = min(ans, dp[n - 1][i]);
}
cout << ans << endl;
}
return 0;
}