【題目描述】
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 110using 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;}