• codevs1260 快餐问题


    题意:

    一个套餐需要a个A,b个B,c个C。

    你生产一个A需要t1,一个B需要t2,一个C需要t3时间。

    你有n台机器。每台每天工作timei时间。

    一件物品只能在一个机器上生产。

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

    每天ABC产量上限是100,n<=10

    解:

    这个DP的状态表示真是奇怪..

    有一种做法是设f[i][j][k][l]表示前i台机器生产j个A,k个B,l个C的最大套餐数量。

    被我的 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 
    ", 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的数据很弱。强数据在洛谷上。

  • 相关阅读:
    Android--将图片存放到我们本地
    Android--将Bitmip转化成字符串
    Android--启动系统的剪切图像功能并返回结果
    Android--从相册中选取照片并返回结果
    Android--启动拍照功能并返回结果
    Android--PullToRefreshListView的onRefreshComplete()不起作用的问题
    Android判断当前的android设备是否处于联网状态
    Android中修改状态栏的颜色和我们App的风格一致
    ListView的多布局中的小问题
    [Android] Activity间切换,传递数据
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9707535.html
Copyright © 2020-2023  润新知