BZOJ原题链接

洛谷原题链接

解决这题得先想到一个贪心:吃饭慢的先排队。

并不会证明(感觉显然

设\(f[i][j][k]\)表示已经排好了前\(i\)人,第一个队伍需要花费的打饭时间为\(j\),第二个队伍需要花费的打饭时间为\(k\),最后一个吃完饭的时刻。

显然这会\(MLE\)(滚动数组也救不了你

实际上,我们可以将\(k\)这一维舍去。设\(S[i]\)表示前\(i\)个人打饭所需要的时间,即前缀和。

则当安排了前\(i\)个人,其中第一个队伍需要花费打饭的时间为\(j\),那么第二个队伍所需要的打饭时间就为\(S[i] - j\)。

于是有状态转移方程:

\(\qquad\qquad f[i][j] = \min\{ f[i][j], \max\{ f[i - 1][j - A[i]], j + B[i] \} \}\)

\(\qquad\qquad f[i][j] = \min\{ f[i][j], \max\{ f[i - 1][j], S[i] - j + B[i] \} \}\)

第一个转移方程表示将第\(i\)个人安排至第一个队伍,最后一个吃完饭的时刻即为原本最晚吃完的和现在第\(i\)个人吃完饭的时刻取\(\max\)。

第二个转移方程是将第\(i\)个人安排至第二个队伍,则不会对第一个队伍的打饭时间造成影响(依旧为\(j\)),取值同理。

\(f\)初始化为极大值,且\(f[0][0] = 0\)。

最后答案即\(\min\limits_{i = 0}^{S[n]}\{ f[n][i] \}\)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 210;
struct dd{
int x, y;
};
dd a[N];
int f[N][N * N], S[N];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline int minn(int x, int y)
{
return x < y ? x : y;
}
inline int maxn(int x, int y)
{
return x > y ? x : y;
}
bool comp(dd x, dd y)
{
return x.y > y.y;
}
int main()
{
int i, j, n, m, mi = 1e9;
n = re();
for (i = 1; i <= n; i++)
{
a[i].x = re();
a[i].y = re();
}
sort(a + 1, a + n + 1, comp);
for (i = 1; i <= n; i++)
S[i] = S[i - 1] + a[i].x;
memset(f, 60, sizeof(f));
f[0][0] = 0;
for (i = 1; i <= n; i++)
for (j = 0, m = S[i]; j <= m; j++)
{
if (j >= a[i].x)
f[i][j] = minn(f[i][j], max(f[i - 1][j - a[i].x], j + a[i].y));
f[i][j] = minn(f[i][j], max(f[i - 1][j], S[i] - j + a[i].y));
}
for (i = 0; i <= S[n]; i++)
mi = minn(mi, f[n][i]);
printf("%d", mi);
return 0;
}

BZOJ1899或洛谷2577 [ZJOI2005]午餐的更多相关文章

  1. 洛谷 2577 [ZJOI2005]午餐——序列dp

    题目:https://www.luogu.org/problemnew/show/P2577 可以从只有一个窗口的角度思考出一个贪心结论.就是应当按吃饭时间(不算打饭时间)从大到小排序.这样交换相邻两 ...

  2. [洛谷P2577] [ZJOI2005]午餐

    洛谷题目链接:[ZJOI2005]午餐 题目描述 上午的训练结束了,THU ACM小组集体去吃午餐,他们一行N人来到了著名的十食堂.这里有两个打饭的窗口,每个窗口同一时刻只能给一个人打饭.由于每个人的 ...

  3. 【题解】洛谷P2577 [ZJOI2005] 午餐(DP+贪心)

    次元传送门:洛谷P2577 思路 首先贪心是必须的 我们能感性地理解出吃饭慢的必须先吃饭(结合一下生活) 因此我们可以先按吃饭时间从大到小排序 然后就能自然地想到用f[i][j][k]表示前i个人在第 ...

  4. 洛谷P2577 [ZJOI2005]午餐 打饭时间作为容量DP

    P2577 [ZJOI2005]午餐 )逼着自己做DP 题意: 有n个人打饭,每个人都有打饭时间和吃饭时间.有两个打饭窗口,问如何安排可以使得总用时最少. 思路: 1)可以发现吃饭时间最长的要先打饭. ...

  5. 洛谷P2577 [ZJOI2005]午餐 dp

    正解:序列dp 解题报告: 传送门! 这题首先要想到一个显然的贪心:每个窗口的排队顺序都是按照吃饭时间从大到小排序的 证明如下: 这种贪心通常都是用微扰法,这题也不例外 现在假如已经确定了每个窗口有哪 ...

  6. 洛谷 P2577 [ZJOI2005]午餐

    这道题目比较难想. 题解: 算法:贪心+dp 容易想到贪心:吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 然后就是dp了: 首先,应该想到f[i][j][k]:前i个人,在1号窗口打饭 ...

  7. 洛谷 P2577 [ZJOI2005]午餐 题解

    每日一题 day56 打卡 Analysis 算法:贪心+dp 容易想到贪心:吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 然后就是dp了: 首先,应该想到f[i][j][k]:前i个 ...

  8. 【洛谷2577】[ZJOI2005] 午餐(较水DP)

    点此看题面 大致题意: 有\(N\)个学生去食堂打饭,每个学生有两个属性:打饭时间\(a_i\)和吃饭时间\(b_i\).现要求将这些学生分成两队分别打饭,求最早何时所有人吃完饭. 贪心 首先,依据贪 ...

  9. Luogu 2577[ZJOI2005]午餐 - 动态规划

    Solution 啊... 我太菜了唔 不看题解是不可能的, 这辈子都不可能的. 首先一个队伍中排队轮到某个人的时间是递增的, 又要加上吃饭时间, 所以只能使吃饭时间递减, 才能满足最优,于是以吃饭时 ...

随机推荐

  1. windows 允许空密码登陆

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa  这个注册表键值下的limitblankpassworduse项 修改为0或者1

  2. svn:Cannot negotiate authentication mechanism

    解决方案:在eclipse->window->preference->team->svn中将svn接口设定为svnkit.

  3. 关于H5唤醒APP的功能实现(千辛万苦啊!)

    首先,我是个后端,写java的,甚至不是搞移动端的,所以js这方面有点底子但不专业,对于出现的错误也请见谅,原来项目要求有个H5页面打开APP的功能就强行要做,没办法就想办法搞一下,网上的教程基本都是 ...

  4. Redis原子计数器incr

    一.前言在一些对高并发请求有限制的系统或者功能里,比如说秒杀活动,或者一些网站返回的当前用户过多,请稍后尝试.这些都是通过对同一时刻请求数量进行了限制,一般用作对后台系统的保护,防止系统因为过大的流量 ...

  5. vmware 共享文件夹

    参考 https://jingyan.baidu.com/article/7f766daf7866be4101e1d0ed.html 只是设置共享文件夹选项还不行,需要从安装vmware的安装路径中找 ...

  6. Spring之jdbcTemplate实现orm

    public List<AppUser> getAppUser(AppUser appUser) { String sql = "select * from appuser a ...

  7. 原生js,通过document.getElementByClassName获取元素的索引值

    let itemList = document.getElementsByClassName('sky-item') // 一行所有元素 let index = 0 for(let i = 0; i& ...

  8. python 最简单的爬虫

    import urllib.request file=urllib.request.urlopen("http://www.qq.com") data=file.read() da ...

  9. C/C++ typedef用法详解(真的很详细)

    第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如:char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针, ...

  10. oracle 中从某天到某天一天一次执行某个函数

    DECLAREv_days INTEGER;v_start VARCHAR2(10);v_end VARCHAR2(10);v_3 INTEGER;v_enddays date;begin v_sta ...