1. 程式人生 > >HDU 1158【簡單dp】

HDU 1158【簡單dp】

set def mon 工資 ret names clu while ace

題意:給你一個項目,需要幾個月來完成買,同時也給你每個月最少需要的工人數。並且告訴你hiring,firing每個工人的錢數,以及每個月應付每個工人的工資。求項目完成時最小花費。

這是個簡單dp,思路就是枚舉一下上一個月和本月的工人數,寫個狀態轉移方程即可。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
#define MAX 6000
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

int s, h, f;
int num[MAX];
int mon;
int dp[MAX][13];
int max(int a, int b) {
    return (a > b) ? a : b;
}

int min(int a, int b) {
    return (a < b) ? a : b;
}
int main(void) {
    int maxx = 0;
    int ans = 0;
    while (~scanf("%d", &mon) && mon) {
        memset(dp, INF, sizeof(dp));
        ans = INF;
        scanf("%d%d%d", &h, &s, &f);
        for (int i = 1; i <= mon; i++) {
            scanf("%d", &num[i]);
            maxx = max(maxx, num[i]);
        }
        if (mon == 1) {
            ans = num[mon] * (h + s);
            printf("%d\n", ans);
        }
        else {
            for (int i = num[1]; i <= maxx; i++) {
                dp[i][1] = i * (h + s);
            }
            for (int i = 2; i <= mon; i++) {
                for (int j = num[i]; j <= maxx; j++) {
                    for (int k = num[i - 1]; k <= maxx; k++) {
                        if (j == k)
                            dp[j][i] = min(dp[j][i - 1] + j * s, dp[j][i]);
                        else if (j > k) {
                            dp[j][i] = min(dp[k][i - 1] + (j - k)*(h + s) + k * s, dp[j][i]);
                        }
                        else {
                            dp[j][i] = min(dp[k][i - 1] + f * (k - j) + s * j, dp[j][i]);
                        }

                    }

                }
            }
            for (int i = num[mon]; i <= maxx; i++) {
                ans = min(ans, dp[i][mon]);
            }
            printf("%d\n", ans);

        }

    }
    return 0;

}







HDU 1158【簡單dp】