二分加dp。dp我用的是顺推,二分查找总时间,对于每个总时间进行dp确定能否在其限制内完成任务。f[i][j]表示前i个工人完成j件a的情况下最多完成多少件b。
f[i + 1][j + k] = max(f[i + 1][j + k], f[i][j] + (t - worker[i + 1].a * k) / worker[i + 1].b);
View Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define maxn 55
#define maxx 1005
struct Worker
{
int a, b;
}worker[maxn];
int n, x, y;
int f[maxn][maxx];
void input()
{
scanf("%d%d%d", &n, &x, &y);
for (int i = 0; i < n; i++)
scanf("%d%d", &worker[i].a, &worker[i].b);
}
bool ok(int t)
{
memset(f, -1, sizeof(f));
for (int i = 0; i <= x && t - worker[0].a * i >= 0; i++)
f[0][i] = (t - worker[0].a * i) / worker[0].b;
for (int i = 0; i < n - 1; i++)
for (int j = 0; j <= x; j++)
{
if (f[i][j] == -1)
break;
for (int k = 0; j + k <= x && t - worker[i + 1].a * k >= 0; k++)
f[i + 1][j + k] = max(f[i + 1][j + k], f[i][j] + (t - worker[i + 1].a * k) / worker[i + 1].b);
}
if (f[n - 1][x] >= y)
return true;
return false;
}
int binarysearch()
{
int l, r, mid;
l = 0;
r = worker[0].a * x + worker[0].b * y;
while (l < r)
{
mid = (l + r) / 2;
if (ok(mid))
r = mid;
else
l = mid + 1;
}
return l;
}
int main()
{
// freopen("D:\\t.txt", "r", stdin);
int t;
scanf("%d", &t);
for (int i = 0; i < t; i++)
{
input();
int ans = binarysearch();
printf("Case %d: %d\n", i + 1, ans);
}
return 0;
}