codevs1260 快餐問題

題意:ide

一個套餐須要a個A,b個B,c個C。spa

你生產一個A須要t1,一個B須要t2,一個C須要t3時間。code

你有n臺機器。每臺天天工做timei時間。blog

一件物品只能在一個機器上生產。get

求你一天最多能生產多少套餐。string

天天ABC產量上限是100,n<=10it

解:io

這個DP的狀態表示真是奇怪..event

有一種作法是設f[i][j][k][l]表示前i臺機器生產j個A,k個B,l個C的最大套餐數量。class

被個人 1 1 1   2 2 2   3   3 2 1 卡掉了,輸出1,答案是0

還有一種作法是設f[i][j][k][l]表示前i臺機器生產j個A,k個B,l個C的所需最少時間。

這是zbtrs提供的。我還沒思考。可是直覺上感受很不對勁....

 


最後是我用的,f[i][j][k]表示前i臺機器生產j個A,k個B時所能生產的最多C數量。

一開始預處理出最大套餐值和最大ABC值。

轉移就是枚舉這一臺/以前的機器生產了多少A和B,而後計算出C來。

注意,一開始的時候可能會從f[0][x][y]之類的不存在的狀態轉移過來。

解決方案是賦值爲-1,特判。初值是f[0][0][0] = 0

有幾個剪枝:第一個是這條生產線不能生產更多的A和B了,這時要break

還有就是這個狀態的C已經滿了,此時不用繼續枚舉轉移了,直接出轉移(goto flag)。

而後就把很嚇人的時間複雜度剪下去了。

 

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #define say(a) printf(#a); printf(" = %d \n", a)
 5 const int N = 110;
 6 
 7 int f[12][N][N], time[N];
 8 int a, b, c;
 9 int t1, t2, t3;
10 
11 int main() {
12     int n;
13     scanf("%d%d%d", &a, &b, &c);
14     scanf("%d%d%d", &t1, &t2, &t3);
15     scanf("%d", &n);
16     int sum = 0, ans = 0;
17     for(int i = 1; i <= n; i++) {
18         scanf("%d", &time[i]);
19         sum += time[i];
20     }
21     int lm = sum / (a * t1 + b * t2 + c * t3);
22     int maxA = std::min(lm * a, 100);
23     int maxB = std::min(lm * b, 100);
24     int maxC = std::min(lm * c, 100);
25 
26     memset(f, -1, sizeof(f));
27     f[0][0][0] = 0;
28     for(int i = 1; i <= n; i++) {
29         f[i][0][0] = 0;
30     }
31     for(int i = 1; i <= n; i++) {
32         for(int j = maxA; j >= 0; j--) {
33             for(int k = maxB; k >= 0; k--) {
34                 /// get f[i][j][k]
35                 for(int jj = j; jj >= 0; jj--) {
36                     for(int kk = k; kk >= 0; kk--) {
37                         if(time[i] < (j - jj) * t1 + (k - kk) * t2) {
38                             goto flag;
39                         }
40                         if(f[i - 1][jj][kk] == -1) {
41                             continue;
42                         }
43                         f[i][j][k] = std::max(f[i][j][k],
44                                               f[i - 1][jj][kk] + (time[i] - (j - jj) * t1 - (k - kk) * t2) / t3);
45                         if(f[i][j][k] >= maxC) {
46                             goto flag;
47                         }
48                     }
49                 }
50                 flag:
51                 int now = std::min(j / a, k / b);
52                 now = std::min(now, f[i][j][k] / c);
53                 ans = std::max(ans, now);
54             }
55         }
56     }
57 
58     printf("%d", ans);
59     return 0;
60 }
AC代碼

 

codevs的數據很弱。強數據在洛谷上。

相關文章
相關標籤/搜索