UVa 10163 - Storage Keepers

传送门

UVa 10163 - Storage Keepers

题意

有N个柜子,M个人,一个柜子只能有一个人来打扫,一个人可以打扫多个柜子,求最大安全系数和这种情况下最少的钱。

思路

$dp[i][j]$表示前i个人打扫j个柜子。
状态转移方程$dp[i][j] = max(dp[i][j], min(dp[i - 1][j - k], value[i] / k))$,不过之前得先让$dp[i][j] = dp[i - 1][j]$,意思是当前这个人不打扫柜子时的情况。

之后根据求出来的值去求最小花费

代码

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int MAXN = 100 + 10;
const int INF = 0x3f3f3f3f;
 
int safe[MAXN], dp[MAXN][MAXN], fee[MAXN][MAXN];
 
int main()
{
    //freopen("input.txt", "r", stdin);
    int sto, n, i, j;
    while (scanf("%d%d", &sto, &n), sto + n)
    {
        memset(dp, 0, sizeof dp);
        memset(fee, 0x3f, sizeof fee);
        for (i = 1; i <= n; i++)
            scanf("%d", &safe[i]);
        for (i = 1; i <= n; i++)
        {
            dp[i - 1][0] = INF;
            for (j = 1; j <= sto; j++)
            {
                dp[i][j] = dp[i - 1][j];
                for (int k = 1; k <= j; k++)
                    dp[i][j] = max(dp[i][j], min(dp[i - 1][j - k], safe[i] / k));
            }
        }
        //printf("%d\n", dp[n][sto]);
        for (i = 1; i <= n; i++)
        {
            fee[i - 1][0] = 0;
            for (j = 1; j <= sto; j++)
            {
                fee[i][j] = fee[i - 1][j];
                for (int k = 1; k <= j; k++)
                    if (safe[i] / k >= dp[n][sto])
                        fee[i][j] = min(fee[i][j], fee[i - 1][j - k] + safe[i]);
            }
        }
        if (dp[n][sto] == 0)
            printf("0 0\n");
        else
            printf("%d %d\n", dp[n][sto], fee[n][sto]);
    }
    return 0;
 
}

Powered by Jekyll and Theme by solid