思路:dp[i][j]表示前i个月最后一个月的总人数为j所花的最小费用,状态移动方程:dp[i][j] = min{dp[i-1][k] + cost[i][j]},其中cost[i][j]是第i月的花费,
1~当k<=j时,第i个月请了人所以cost[i][j] = j*salary + (j-k)*hire
2~当k>j时,第i个月炒了人,所以cost[i][j] = j*salary + (k-j)*fire
#include<stdio.h>
#include<string.h>
const int INF=99999999;
int dp[15][10010];
int people[15];
int main(){
//freopen("input.txt","r",stdin);
int n;
int hire,salary,fire;
while(scanf("%d",&n) && n){
scanf("%d%d%d",&hire,&salary,&fire);
int max_people=0;
int i,j,k;
for(i=1;i<=n;i++){
scanf("%d",&people[i]);
if(max_people<people[i])
max_people=people[i];
}
for(i=people[1];i<=max_people;i++) //初始化第一个月
dp[1][i]=i*salary+i*hire;
int min;
for(i=2;i<=n;i++){
for(j=people[i];j<=max_people;j++){
min=INF; //有了这个前面就不需要用O(n^2)初始化dp了。
for(k=people[i-1];k<=max_people;k++)
if(min>dp[i-1][k]+(j>=k?(j*salary+(j-k)*hire):(j*salary+(k-j)*fire)))
min=dp[i-1][k]+(j>=k?(j*salary+(j-k)*hire):(j*salary+(k-j)*fire));
dp[i][j]=min;
}
}
min=INF;
for(i=people[n];i<=max_people;i++)
if(min>dp[n][i])
min=dp[n][i];
printf("%d\n",min);
}
return 0;
}