HDOJ 1158 DP
DP公式个人感觉如下ans[m][i]=min(ans[m-1][k]+diff),对每个need[m-1]<=k<=maxNeed。其中,m是大于等于2的月份(1月份的ans直接初始化)。need数组存放某月需要的员工数,maxNeed需要员工数最多的月份的员工数。diff是员工数从(m-1)月的 i 变成这个m月的k所需要支付的差值。
这个公式想出来以后,发现题目没有给员工数的最大数量,如果员工数很多,假设为10000,则最大运算量为12*10000*10000,上十亿了。如果是这样肯定是要超时的。其实,后来发现输入数据中每月的员工数量是不超过1000的,这样,最大运算量不超过千万,所以可以过。
#include <iostream> using namespace std; const int MAX_MONTH = 12; const int MAX_STAFF = 10000; int ans[MAX_MONTH + 1][MAX_STAFF]; inline int getMin(int a,int b) { return a < b ? a : b; } int main () { int month,maxNeed = -1; int hire,salary,fire; int need[MAX_MONTH + 1]; while (scanf("%d",&month) != -1 && month != 0) { memset(ans,0,sizeof(ans)); scanf("%d%d%d",&hire,&salary,&fire); for (int i = 1;i <= month;i ++) { scanf("%d",&need[i]); maxNeed = maxNeed > need[i] ? maxNeed : need[i]; } for (int i = need[1];i <= maxNeed;i ++)/* 第一个月的需要初始化 */ ans[1][i] = (hire + salary) * i; for (int i = 2;i <= month;i ++) { for (int j = need[i];j <= maxNeed;j ++)/* 这个月的雇员数量 */ { int minNeed = -1; for (int k = need[i - 1];k <= maxNeed;k ++)/* 上个月的雇员数量 */ { if (k < j)/* 上个月的雇员数比这个月少 */ { if (minNeed == -1) minNeed = ans[i - 1][k] + hire * (j - k) + salary * j; else minNeed = getMin(minNeed,ans[i - 1][k] + hire * (j - k) + salary * j); } else/* 上个月雇员数大于等于这个月的 */ { if (minNeed == -1) minNeed = ans[i - 1][k] + fire * (k - j) + salary * j; else minNeed = getMin(minNeed,ans[i - 1][k] + fire * (k - j) + salary * j); } } ans[i][j] = minNeed; } } int min = -1; for (int i = need[month];i <= maxNeed;i ++) { if (min == -1) min = ans[month][i]; else min = getMin(min,ans[month][i]); } printf("%d\n",min); } return 0; }

浙公网安备 33010602011771号