hoj3433

二分加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;
}
posted @ 2011-03-19 15:48  金海峰  阅读(154)  评论(0编辑  收藏  举报