思路:
对于这一类关于最大值最小问题,我们一般采用二分求解。
考虑用二分枚举出一个时间T,设f[i][j]表示前i个人做了j个项目1的子项目,
最多可以再做多少项目2的子项目。
动态转移方程为:
f
[
i
]
[
j
]
=
m
a
x
(
f
[
i
]
[
j
]
,
f
[
i
−
1
]
[
j
−
k
]
+
(
T
−
k
∗
x
[
i
]
)
/
y
[
i
]
)
;
f[i][j] = max(f[i][j], f[i - 1][j - k] + (T - k * x[i]) / y[i]);
f[i][j]=max(f[i][j],f[i−1][j−k]+(T−k∗x[i])/y[i]);
考虑枚举一个k表示前i-1个人做了K个项目1,那剩下的时间为T-k * x[i],
还能做项目二的个数即为 (T - k * x[i]) / y[i])
#include <cstdio>
#include <iostream>
#include <cstring>
#define reg register
using namespace std;
const int N = 1e3 + 10;
int n, m, x[N], y[N], f[N][N], ans;
bool check(int T)
{
memset(f, -127, sizeof(f));
f[0][0] = 0;
for(reg int i = 1; i <= n; i++)
for(reg int j = 0 ; j <= m; j++)
for(reg int k = 0; k <= j; k++)
if(T - k * x[i] >= 0)
f[i][j] = max(f[i][j], f[i - 1][j - k] + (T - k * x[i]) / y[i]);
if(f[n][m] >= m) return 1;
return 0;
}
int main()
{
freopen("company.in", "r", stdin);
freopen("company.out", "w", stdout);
scanf("%d%d", &n, &m);
for(reg int i = 1; i <= n; i++) scanf("%d%d", &x[i], &y[i]);
int l = 1, r = 999999;
while(l <= r)
{
int mid = (l + r) >> 1;
if(check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d\n", ans);
return 0;
}