UVa 10163 仓库守卫
https://vjudge.net/problem/UVA-10163
题意:
有n个仓库,m个管理员,每个管理员有一个能力值P(接下来的一行有m个数,表示每个管理员的能力值)
每个仓库只能由一个管理员看管,但是每个管理员可以看管k个仓库(但是这个仓库分配到的安全值只有p/k,k=0,1,...),
每个月公司都要给看管员工资,雇用的管理员的工资即为他们的能力值p和,问,使每个仓库的安全值最高的前提下,使的工资总和最小。
输出最大安全值,并且输出最少的花费。
思路:
先求出安全系数来。d[i][j]表示前i个守卫看守前j个仓库的最小安全系数的最大值。之后第二次DP求最小花费。
1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn = 10000 + 5; 8 const int INF = 10000000; 9 10 int n, m; 11 int p[35]; 12 int d[maxn][maxn]; 13 14 int main() 15 { 16 //freopen("D:\\txt.txt", "r", stdin); 17 while (cin >> n >> m && n&& m) 18 { 19 for (int i = 1; i <= m; i++) 20 cin >> p[i]; 21 for (int i = 0; i <= m; i++) 22 d[i][0] = INF; 23 for (int i = 1; i <= n; i++) 24 d[0][i] = 0; 25 for (int i = 1; i <= m; i++) 26 { 27 for (int j = 1; j <= n; j++) 28 { 29 d[i][j] = d[i - 1][j]; 30 for (int k = 0; k < j; k++) 31 d[i][j] = max(d[i][j], min(d[i - 1][k], p[i] / (j - k))); 32 } 33 } 34 if (!d[m][n]) 35 { 36 cout << "0 0" << endl; 37 continue; 38 } 39 int x = d[m][n]; 40 for (int i = 0; i <= m; i++) 41 d[i][0] = 0; 42 for (int i = 1; i <= n; i++) 43 d[0][i] = INF; 44 for (int i = 1; i <= m;i++) 45 for (int j = 1; j <= n; j++) 46 { 47 d[i][j] = d[i - 1][j]; 48 for (int k = 0; k < j;k++) 49 if (p[i] / (j-k) >= x) 50 d[i][j] = min(d[i][j], d[i - 1][k] + p[i]); 51 } 52 cout << x << " " << d[m][n] << endl; 53 } 54 return 0; 55 }