小记:这题的转移方程 需要动脑,奈何想不到,就做不到。我还是看了一下别人的dp[i][j] 的意思,然后转移方程自己写出来了。 唉,dp就是定义和转移方程难想。无后效性,和最优解,这两个必须满足,才能动用dp。
思路:dp,每个dp的转移方程若是不是自己想出来的,那么这道题,个人觉得收获已经不会大了。
dp[i][j] 表示前i个月,在第i个月的时候有j人的最小花费。
转移方程:dp[i][j] = min(dp[i-1][k] + cost, dp[i][j]) ( k >= person[i-1] && k <= personMax)
if(j => k) cost = (j - k) * hire + j * salary;
if(j <= k ) cost = (k - j) * fire + j * salary;
person[i] 是第i个月 需要的人数,personMax是 max(person[i]) (i >= 1 && i <= n)
初始化第一个月的值即可。
dp[1][i] = i * (hire + salary); (i >= person[1] && i <= personMax)
最后的answer = min(dp[n][i]) (i >= person[n] && i <= personMax)
代码:
#include <stdio.h>
#include <string.h>
#include <stack>
#include <iostream>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
const int MAX_ = 15;
const int MAX = 0x7fffffff;
int person[MAX_];
int dp[MAX_][MAX_*100];
int main() {
int T;
int m, k, n, hire, salary, fire, personMax;
while(scanf("%d",&n),n){
personMax = -1;
scanf("%d%d%d",&hire,&salary,&fire);
for(int i = 1; i <= n; ++i){
scanf("%d",&person[i]);
personMax = max(personMax,person[i]);
}
for(int i = person[1]; i <= personMax; ++i){
dp[1][i] = i * (hire + salary);
}
for(int i = 2; i <= n; ++i){
for(int j = person[i]; j <= personMax; ++j){
int minm = MAX;
for(int k = person[i-1]; k <= personMax; ++k){
int cost;
if(j > k){
cost = (j - k) * hire + j * salary;
}
else {
cost = (k - j) * fire + j * salary;
}
minm = min(minm,dp[i-1][k] + cost);
}
dp[i][j] = minm;
}
}
int ans = MAX;
for(int i = person[n]; i <= personMax; ++i){
ans = min(ans,dp[n][i]);
}
printf("%d\n",ans);
}
return 0;
}