[DP][贪心]午餐

题目描述

上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂。这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭。由于每个人的口味(以及胃口)不同,所以他们要吃的菜各有不同,打饭所要花费的时间是因人而异的。另外每个人吃饭的速度也不尽相同,所以吃饭花费的时间也是可能有所不同的。

THU ACM小组的吃饭计划是这样的:先把所有的人分成两队,并安排好每队中各人的排列顺序,然后一号队伍到一号窗口去排队打饭,二号队伍到二号窗口去排队打饭。每个人打完饭后立刻开始吃,所有人都吃完饭后立刻集合去六教地下室进行下午的训练。

现在给定了每个人的打饭时间和吃饭时间,要求安排一种最佳的分队和排队方案使得所有人都吃完饭的时间尽量早。

假设THU ACM小组在时刻0到达十食堂,而且食堂里面没有其他吃饭的同学(只有打饭的师傅)。每个人必须而且只能被分在一个队伍里。两个窗口是并行操作互不影响的,而且每个人打饭的时间是和窗口无关的,打完饭之后立刻就开始吃饭,中间没有延迟。

现在给定N个人各自的打饭时间和吃饭时间,要求输出最佳方案下所有人吃完饭的时刻。

输入输出格式

输入格式:
第一行一个整数N,代表总共有N个人。

以下N行,每行两个整数 Ai,Bi。依次代表第i个人的打饭时间和吃饭时间。

输出格式:
一个整数T,代表所有人吃完饭的最早时刻。

输入输出样例

输入样例
5
2 2
7 7
1 3
6 4
8 5
输出样例
17
说明

所有输入数据均为不超过200的正整数。

分析

我们想一想,可得一个简单的贪心思想:吃饭时间长的,先排队
所以按这个排个序先
然后我们设fi表示队列1排队时间为i的时候的总时间
易得:
k=1~n
fi+ak=min{max(fi,i+ak+bk) (当k加入队列1时)
fi=max(fi,sum[a1~i -j+bk) (当k加入队列2时)
只要处理一个前缀和就行

#include <iostream>
#include <cstdio>
#include <algorithm>
#define rep(i,a,b) for (i=a;i<=b;i++)
using namespace std;
int n;
struct M
{
    int a,b;
}a[201];
int s[201],sut;
int f[40001];
int ans;
int i,j;
bool cmp(M a,M b)
{
    return a.b>b.b;
}
int main()
{
    scanf("%d",&n);
    rep(i,1,n)
    scanf("%d%d",&a[i].a,&a[i].b);
    sort(a+1,a+n+1,cmp);
    rep(i,1,40000) f[i]=2147483647;
    rep(i,1,n)
    s[i]=a[i].a+s[i-1];
    rep(i,1,n)
    {
        for (j=sut;j>=0;j--)
        {
            f[j+a[i].a]=min(f[j+a[i].a],max(f[j],j+a[i].a+a[i].b));
            f[j]=max(f[j],s[i]-j+a[i].b);
        }
        sut+=a[i].a;
    }
    ans=2147483647;
    rep(i,1,sut)
    ans=min(ans,f[i]);
    printf("%d",ans);
}
贪心算法不是动态规划(DP)。虽然贪心算法和动态规划都有通过局部最优解来解决全局最优解,但二者存在明显区别。贪心算法在得到局部最优解时,不考虑之前的最优解,只考虑当前状态的局部最优解;而动态规划则会考虑到之前状态的最优解,并且注重寻找状态转移方程[^2]。 动态规划是一种算法思想,是对问题不断细分,时刻更新、回溯直至最后结束执行,也可称为带着记忆的递归,是自底向上的回溯法,可能在某个节点不是最优解,但最终一定是最优解。贪心算法则通常是从当前状态出发,做出当前看似最优的选择,不进行回溯,且不一定能得到全局最优解[^2][^3]。 以下是一个简单的贪心算法示例(找零问题)和动态规划示例(背包问题)对比: ```python # 贪心算法 - 找零问题 def greedy_change(amount, coins): coins.sort(reverse=True) change = [] for coin in coins: while amount >= coin: amount -= coin change.append(coin) return change amount = 63 coins = [25, 10, 5, 1] result = greedy_change(amount, coins) print("贪心算法找零结果:", result) # 动态规划 - 01背包问题 def knapsack(weights, values, capacity): n = len(weights) dp = [[0 for _ in range(capacity + 1)] for _ in range(n + 1)] for i in range(1, n + 1): for w in range(1, capacity + 1): if weights[i - 1] <= w: dp[i][w] = max(values[i - 1] + dp[i - 1][w - weights[i - 1]], dp[i - 1][w]) else: dp[i][w] = dp[i - 1][w] return dp[n][capacity] weights = [2, 3, 4, 5] values = [3, 4, 5, 6] capacity = 8 result = knapsack(weights, values, capacity) print("动态规划01背包问题结果:", result) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值