UVA10163 Storage Keepers (动态规划)

星夜行 2018-05-05

$dp[i][j]$表示前$i$个仓库由前$j$个人来守卫能取得的最大安全值;

$cost[i][j]$表示前$i$个仓库由前$j$个人来守护在能取得的最大安全值的情况下的最小花费。

AC代码

//#define LOCAL
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 100 + 5;
const int maxm = 30 + 5;
int a[maxm];
int dp[maxn][maxm], cost[maxn][maxm];

void solve(int n, int m) {
    // init
    memset(dp, 0, sizeof(dp));

    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            // not choose j
            dp[i][j] = dp[i][j-1];
            // choose j
            for(int k = 1; k <= i; k++) {
                int x;
                if(k == i) x = a[j] / k;
                else x = min(a[j] / k, dp[i-k][j-1]);

                if(x > dp[i][j]) {
                    dp[i][j] = x;
                }
            }
        }
    }

    memset(cost, INF, sizeof(cost));
    memset(cost[0], 0, sizeof(cost[0]));
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            cost[i][j] = cost[i][j-1];
            for(int k = 1; k <= i; k++) {
                int safe = a[j] / k;
                if(safe >= dp[n][m]) {
                    cost[i][j] = min(cost[i][j], cost[i-k][j-1] + a[j]);
                }
            }
        }
    }
}

int main() {
#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif
    int n, m;
    while(scanf("%d%d", &n, &m) == 2 && n && m) {
        for(int i = 1; i <= m; i++) {
            scanf("%d", &a[i]);
        }
        solve(n, m);
        printf("%d %d\n", dp[n][m], dp[n][m]==0?0:cost[n][m]);
    }
    return 0;
}

如有不当之处欢迎指出!

相关推荐