標籤:style blog http color io os ar for div
題意:
有n個員工,每個員工完成一件A任務和一件B任務的時間給出,問要完成x件A任務y件B任務所需的最短時間是多少
思路:
DP + 二分我也是第一次見到,這個我只能說太難想了,根本想不到。
dp[i][j]表示在t時間內前i個人完成j件A任務後所能完成B任務的最大數量。
代碼中還有一些注釋。
1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 7 int dp[55][205], a[205], b[205]; 8 int _, n, x, y, kase = 0; 9 10 bool check(int t)11 {12 memset(dp, -1, sizeof(dp));13 dp[0][0] = 0;14 15 for(int i = 1; i <= n; ++i)16 {17 if(dp[i][x] >= y) return true; 18 for(int j = 0; j <= x; ++j)19 {20 if(dp[i - 1][j] != -1)21 {22 int temp = min(t/a[i], x-j); //枚舉第i個人可以做的A任務的個數23 for(int k = 0; k <= temp; ++k)24 {25 int t1 = (t - a[i] * k) / b[i]; //計算第i個人做k件A任務,所能做的B任務的個數26 dp[i][j + k] = max(dp[i][j + k], dp[i - 1][j] + t1); //選最優解27 }28 }29 }30 }31 32 if(dp[n][x] >= y) return true;33 return false;34 }35 36 int main(void)37 {38 #ifdef LOCAL39 freopen("3433in.txt", "r", stdin);40 #endif41 42 scanf("%d", &_);43 while(_--)44 {45 scanf("%d%d%d", &n, &x, &y);46 for(int i = 1; i <= n; ++i)47 scanf("%d%d", &a[i], &b[i]);48 49 int l = 0, r = a[1] * x + b[1] * y;50 int ans = r;51 while(l <= r)52 {53 int mid = (l + r) >> 1;54 if(check(mid))55 {56 ans = mid;57 r = mid - 1;58 }59 else l = mid + 1;60 }61 62 printf("Case %d: %d\n", ++kase, ans);63 }64 65 return 0;66 }代碼君
HDU 3433 (DP + 二分) A Task Process