• 洛谷P2577 午餐【贪心】【线性dp】


    题目https://www.luogu.org/problemnew/show/P2577

    题意:n个人每个人有一个打饭时间和吃饭时间,将他们分成两个队伍。每个人打到饭之后就马上去吃饭。问怎么安排可以让总体的吃饭时间最短。

    思路:首先贪心还是很好想的。某个队伍的总吃饭时间实际上是打饭结束+吃饭时间最晚的那个时间。

    一个队伍前面的那些人,如果他们吃完饭的时间都不超过总的排队时间的话,根本不需要考虑他们。而队伍的排队时间如果安排好了,是固定的。跟安排的顺序没有关系。

    所以我们应该要把吃饭时间长的往前放。因为排队时间不受顺序影响但是吃饭时间受顺序的影响。

    然后我们可以考虑怎么给他们分成两队。

    首先可以考虑$dp[i][j][k]$表示考虑到第$i$个人,第一条队伍排队时间是$j$第二条队伍排队时间是$k$的时候,最早全部吃完饭的时间。

    但是我们发现$j$和$k$存在关系,因为两个队伍总的排队时间是固定的。所以我们可以用$sum[i]$来维护排队时间的前缀和。就可以减少一个维度了。

    所以我们可以用$dp[i][j]$表示考虑到第$i$个人,第一条队伍排队时间是$j$最早全部吃完饭的时间。此时显然第二条队伍的排队时间是$sum[i] - j$

    于是有$dp[i][j] = min(max(dp[i-1][j-get[i]], j + eat[i]), max(dp[i - 1][j], sum[i] - j + eat[i]))$分别表示第$i$个人排在第一个队伍和排在第二个队伍。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<map>
     4 #include<set>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<cmath> 
     9 #include<stack>
    10 #include<queue>
    11 #include<iostream>
    12 
    13 #define inf 0x3f3f3f3f
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<int, int> pr;
    17 
    18 int n;
    19 const int maxn = 205;
    20 struct node{
    21     int get, eat;
    22 }stu[maxn];
    23 int sum[maxn];
    24 int dp[maxn][maxn * maxn * 2];
    25 
    26 bool cmp(node a, node b)
    27 {
    28     return a.eat > b.eat;
    29 }
    30 
    31 int main()
    32 {
    33     scanf("%d", &n);
    34     memset(dp, 0x3f, sizeof(dp));
    35     for(int i = 1; i <= n; i++){
    36         scanf("%d%d", &stu[i].get, &stu[i].eat);
    37     }
    38     sort(stu + 1, stu + 1 + n, cmp);
    39     
    40     for(int i = 1; i <= n; i++){
    41         sum[i] = sum[i - 1] + stu[i].get;
    42     }
    43     dp[0][0] = 0;
    44     for(int i = 1; i <= n; i++){
    45         for(int j = 0; j <= sum[i]; j++){
    46             if(j >= stu[i].get)dp[i][j] = min(dp[i][j], max(dp[i - 1][j - stu[i].get], j + stu[i].eat));
    47             dp[i][j] = min(dp[i][j], max(dp[i - 1][j], sum[i] - j + stu[i].eat));
    48         }
    49     }
    50     
    51     int ans = inf;
    52     for(int j = 0; j <= sum[n]; j++){
    53         ans = min(ans, dp[n][j]);
    54     }
    55     printf("%d
    ", ans);
    56     return 0;
    57 }
  • 相关阅读:
    构造并判断二叉搜索树-js
    构造树并判断是否对称
    旋转图像
    螺旋矩阵
    链表实现快速排序
    任务调度器
    队列的实现
    最大矩形
    棒球比赛
    复原IP地址
  • 原文地址:https://www.cnblogs.com/wyboooo/p/11106723.html
Copyright © 2020-2023  润新知