现在的位置: 首页 > 综合 > 正文

[我也简述一下题目]软件公司

2012年09月06日 ⁄ 综合 ⁄ 共 1148字 ⁄ 字号 评论关闭

【题目描述】

n个人,两个项目,各有m个相同部分。每个人完成某个项目的一个部分的时间不同,问最少时间。

【输入格式】

第一行:人数n和部分个数m。

接下来的n行,每行两个数:第i个人完成两个项目的一个部分各需要的时间。

【输出格式】

一行:最快时间。

【样例输入】

3 20

1 1

2 4

1 6

【样例输出】

18

【数据范围】

1<=n,m<=100。

【分析】

二分枚举所用的总的时间,然后用动态规划进行判断是否可以完成。类似唐山一中的同学出的《绿色通道》那道题。但是比那道题目简单。

动归判断:

当前需要判断的时间为mid,用f[i][j]代表前i个人,完成j份第一个项目,第二份项目最多可以完成几份。状态转移方程为f[i][j] = max(f[i - 1][j - k] + (mid - k * w[i][0]) / w[i][1])。最后判断f[n][m]是否大于m即可。

//problem: software company
//by Sephiroth Lee
//date: 10/9/2010
#include <stdio.h>
#include <string.h>
#include <iostream>
#define MAXN 110
using namespace std;
int w[MAXN][2],f[MAXN][MAXN];
int n,m,max_time,l,r,mid;
bool check(int mid) {
  memset(f,-1,sizeof(f));
  f[0][0] = 0;
  for (int i = 1;i <= n;++i)
    for (int j = 0;j <= m;++j) {
      if (f[i - 1][j] < 0) continue;
      for (int k = 0;(j + k <= m) && (mid >= w[i][0] * k);++k)
        if (f[i][j + k] < f[i - 1][j] + (mid - w[i][0] * k) / w[i][1])
          f[i][j + k] = f[i - 1][j] + (mid - w[i][0] * k) / w[i][1];
    }
  return f[n][m] >= m;
}
int main() {
  freopen("software.in","r",stdin);
  freopen("software.out","w",stdout);
  scanf("%d%d",&n,&m);
  for (int i = 1;i <= n;++i) {
    scanf("%d%d",&w[i][0],&w[i][1]);
    if (w[i][0] > max_time)
      max_time = w[i][0];
    if (w[i][1] > max_time)
      max_time = w[i][1];
  }
  r = max_time * m;
  l = 1;
  while (l <= r) {
    mid = (l + r) / 2;
    if (check(mid))
      r = mid - 1;
    else
      l = mid + 1;
  }
  printf("%d\n",l);
  return 0;
}

抱歉!评论已关闭.