hdu1158_Employment Planning DP

题目大意:给定月数n,给定雇佣一个人的花费hi,每个人一个月的工资sa和开除一个人的花费fi。再给定每个月需要的最少人数num[i]。求每月怎样安排雇佣和开除人,使得n个月的花费最少

maxn = max(num[i]);
dp[i][j]:第i月雇j个人的花费
初始化:dp[1][i] = i*(hi+fa);
状态转移:
(1)如果该月雇佣的人数j>=上月雇佣的人数k:dp[i][j]=min(dp[i][j],dp[i-1][k]+j*sa+(j-k)*hi);
(2)反之:dp[i][j]=min(dp[i][j],dp[i-1][k]+j*sa+(k-j)*fi);
最后ans = min(dp[n][i]);(num[n]<=i<=maxn);

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int INF = 999999999;
const int N = 15;
const int M = 1010;
int dp[N][M];//第i个月雇j个人的花费
int num[N];//人数
int hi, sa, fi;
int n;

int main()
{//可以多雇人,使费用降低,雇人上限maxn
    while(~scanf("%d", &n) && n)
    {
        scanf("%d %d %d", &hi, &sa, &fi);
        int maxn = -INF;
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &num[i]);
            maxn = max(maxn, num[i]);
        }
        memset(dp, 0x3f, sizeof(dp));//求最小值,将dp初始化为无穷大
        for(int i = 1; i <= maxn; ++i)
            dp[1][i] = i*(hi+sa);
        for(int i = 2; i <= n; ++i)
            for(int j = num[i]; j <= maxn; ++j)      //该月的状态
                for(int k = num[i-1]; k <= maxn; ++k)//由上月转移而来
                    if(j>=k) dp[i][j] = min(dp[i][j], dp[i-1][k]+j*sa+(j-k)*hi);
                    else dp[i][j] = min(dp[i][j], dp[i-1][k]+j*sa+(k-j)*fi);
        int ans = INF;
        for(int i = num[n]; i <= maxn; ++i)
            ans = min(ans, dp[n][i]);
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/81408751
今日推荐