您的位置:首页 > 其它

UVA-10163 Storage Keepers (DP多次)

2016-04-28 09:21 337 查看
Randy Company has
N (1
≤ N
≤ 100) storages. Company wants some men to keep them safe. Nowthere are
M (1
≤ M
≤ 30) men asking for the job. Company will choose several from them. RandyCompany employs men following these rules:

Each keeper has a number
Pi (1
≤ Pi
≤ 1000) , which stands for their ability.

All storages are the same as each other.

A storage can only be lookd after by one keeper. But a keeper can look after several storages. If akeeper’s ability number is
Pi, and he looks after
K storages, each storage that he looks after hasa safe number
Uj
= Pi
÷ K.(Note:
Uj,
Pi
and K are all integers). The storage which is lookedafter by nobody will get a number 0.

If all the storages is at least given to a man, company will get a safe line
L = min
Uj

Every month Randy Company will give each employed keeper a wage according to his abilitynumber. That means, if a keeper’s ability number is
Pi, he will get
Pi
dollars every month. Thetotal money company will pay the keepers every month is
Y dollars.

Now Randy Company gives you a list that contains all information about
N,
M,
P, your task is givecompany a best choice of the keepers to make the company pay the least money under the conditionthat the safe line
L is the highest.

Input

The input file contains several scenarios. Each of them consists of 2 lines:

The first line consists of two numbers (N
and M), the second line consists of
M numbers, meaning

Pi
(i
= 1..M). There is only one space between two border numbers.The input file is ended with
N = 0 and
M = 0.

Output

For each scenario, print a line containing two numbers
L(max) and
Y (min). There should be a spacebetween them.

Sample Input

21

7

12

10 9

25

10 8 6 4 154111100

Sample Output

3710 108 1800 

题意:

给你n个仓库,m个人,第i个人的能力值为pi,每个人可守卫多个仓库,每个仓库只能被一人守卫,若第i个人守护k个仓库,则那些仓库的安全值为pi/k的整数部分,设所有仓库中安全值最低的为t,要求t最大的情况下,消耗最少的能力值。

分析:

第一次dp,求出n个仓库m个人可获得的最大的t。

f[i][j]表示前i个人守护j个仓库的最低安全值,可得f[i][j]=max(f[i][j],min(pi/k,f[i-1][j-k]))

第二次dp,求出在安全值为t的情况下,消耗最少的能力值。

g[i][j]表示前i个人守护j个仓库在安全值最大情况下花费最少的能力值,可得当pi/k>=f[m]
时,g[i][j]=min(g[i][j],g[i-1][j-k]+pi)

以上k均表示第i个人守护k个仓库时的情况。#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
const int N=105;
const int mod=1e9+7;

int p
,f

,g

;

int main() {
int n,m;
while (cin>>n>>m&&n) {
for (int i=1; i<=m; i++) {
cin>>p[i];
}
memset(f, 0, sizeof(f));
memset(g, INF, sizeof(g));
for (int i=1; i<=m; i++) {
f[i-1][0]=INF;
for (int j=1; j<=n; j++) {
f[i][j]=f[i-1][j];
for (int k=1; k<=j; k++) {
f[i][j]=max(min(p[i]/k, f[i-1][j-k]),f[i][j]);
}
}
}
if (f[m]
==0) {
g[m]
=0;
} else {
for (int i=1; i<=m; i++) {
g[i-1][0]=0;
for (int j=1; j<=n; j++) {
g[i][j]=g[i-1][j];
for (int k=1; k<=j; k++) {
if (p[i]/k>=f[m]
) {
g[i][j]=min(g[i][j], g[i-1][j-k]+p[i]);
}
}
}
}
}

cout<<f[m]
<<" "<<g[m]
<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: