zoukankan      html  css  js  c++  java
  • BZOJ 1899: [Zjoi2004]Lunch 午餐 DP

    题意

    n个人,每个人有打饭时间和吃饭时间,有两个打饭队列,求最后一个人吃完饭的时间最小值。
    n,吃饭时间,打饭时间 <= 200

    题解

    发现数据范围小,可以想到n^3算法。

    首先对于一个队列,内部顺序一定是吃饭吃的慢的放在前面。所以先按b从大到小排序。

    设f[i][j]表示前i个人,1号队列总打饭时间为j时的 最慢的人吃完的时间。答案就是f[n][j]的最小值。

    设a为打饭时间,b为吃饭时间,转移显然:

    • f[i][j+b[i]]=min(f[i][j+b[i]],max(f[i-1][j],j+a[i]+b[i]))
    • f[i][j]=max(f[i-1][j],suma[i-1]-j+a[i]+b[i])

    因为求出a的前缀和,知道1号队列打饭时间,就知道2号队列打饭时间。

    再加上滚动。

    有点模拟思想的DP。

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 205;
    struct node {
        int a, b;
        inline bool operator <(const node &o)const {
            return b > o.b;
        }
    }p[MAXN];
    int n, dp[MAXN*MAXN];
    int main () {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
            scanf("%d%d", &p[i].a, &p[i].b);
        sort(p + 1, p + n + 1);
        memset(dp, 0x3f, sizeof dp);
        dp[0] = 0; int sum = 0;
        for(int i = 1; i <= n; ++i) {
            for(int j = sum; j >= 0; --j) {
                dp[j + p[i].a] = min(dp[j + p[i].a], max(dp[j], j + p[i].a + p[i].b));
                dp[j] = max(dp[j], sum - j + p[i].a + p[i].b);
            }
            sum += p[i].a;
        }
        int ans = 1000000000;
        for(int j = 0; j <= sum; ++j)
            ans = min(ans, dp[j]);
        printf("%d
    ", ans);
    }
    
  • 相关阅读:
    Codeforces Round #631 (Div. 2)
    Codeforces Round #500 (Div. 2) [based on EJOI]
    KMP+状态机
    状态机模型
    最短编辑距离
    stringstream读入-最优乘车
    多重背包
    Codeforces:B. New Year and Ascent Sequence
    查找目录下所有文件使用到的宏
    QProcess调用外部程序并带参执行
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039219.html
Copyright © 2011-2022 走看看