您的位置:首页 > 其它

uva10163 双重dp

2016-03-07 16:34 309 查看
代码:

题意:

有n个仓库(最多100个),m个管理员(最多30个),每个管理员有一个能力值P(接下来的一行有m个数,表示每个管理员的能力值)

每个仓库只能由一个管理员看管,但是每个管理员可以看管k个仓库(但是这个仓库分配到的安全值只有p/k,k=0,1,…),

每个月公司都要给看管员工资,雇用的管理员的工资即为他们的能力值p和,问,使每个仓库的安全值最高的前提下,使的工资总和最小。

输出最大安全值,并且输出最少的花费。

思路:

题目有个限制是:所有物品里面最小的那个安全值即是总的安全值。

第一个dp[i, j] : 前i个人照看前j个物品的最大安全值。

第二个dp[i, j] : 在得到最大安全值的前提下前i个人照看前j个物品的最少花费。

#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>

const int INF = 0x3f3f3f3f;
const int maxn = 110;
const int maxm = 40;
int n,m,dp[maxm][maxn],p[maxm];
int safe,cost;

bool solve() {
for(int i = 0; i <= m; i++)
dp[i][0] = INF;
for(int i = 1; i <= n; i++)
dp[0][i] = 0;

for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n; j++) {
dp[i][j] = dp[i - 1][j];
for(int k = 0; k < j ; k++) //j - k表示i看管的仓库数
dp[i][j] = max(dp[i][j],min(dp[i - 1][k],p[i]/(j - k)));
}
}
if(dp[m]
)
safe = dp[m]
;
else
return false;
for(int i = 0; i <= m; i++)
dp[i][0] = 0;
for(int i = 1; i <= n; i++)
dp[0][i] = INF;

for(int i = 1; i <= m ;i ++)
for(int j = 1; j <= n; j++) {
dp[i][j] = dp[i - 1][j];
for(int k = 0; k < j ; k++)
if(p[i]/(j - k) >= safe)
dp[i][j] = min(dp[i][j],dp[i - 1][k] + p[i]);
}
cost = dp[m]
;
return true;
}
int main() {

while(scanf("%d %d",&n,&m) && m && n) {
memset(dp,0,sizeof(dp));
for(int i = 1; i <= m; i++)
scanf("%d",&p[i]);
if(solve())
printf("%d %d\n",safe,cost);
else
printf("0 0\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: