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;
}
發佈了111 篇原創文章 · 獲贊 38 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章