P2157 [SDOI2009]学校食堂

P2157 [SDOI2009]学校食堂

题意:

小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭。学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴。当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数表示。 由于人手不够,食堂每次只能为一个人做菜。做每道菜所需的时间是和前一道菜有关的,若前一道菜的对应的口味是a,这一道为b,则做这道菜所需的时间为(a or b)-(a and b),而做第一道菜是不需要计算时间的。其中,or 和and 表示整数逐位或运算及逐位与运算,C语言中对应的运算符为“|”和“&”。

学生数目相对于这个学校还是比较多的,吃饭做菜往往就会花去不少时间。因此,学校食堂偶尔会不按照大家的排队顺序做菜,以缩短总的进餐时间。

虽然同学们能够理解学校食堂的这种做法,不过每个同学还是有一定容忍度的。也就是说,队伍中的第i 个同学,最多允许紧跟他身后的Bi 个人先拿到饭菜。一旦在此之后的任意同学比当前同学先拿到饭,当前同学将会十分愤怒。因此,食堂做菜还得照顾到同学们的情绪。 现在,小F 想知道在满足所有人的容忍度这一前提下,自己的学校食堂做完这些菜最少需要多少时间。

题解:

状压dp不难看出,但是不会写
每个人既要考虑前面的人,也要顾虑后面的情况
如何确定动态转移方程:

  1. 我们可以认为已经处理了前i-1个情况,正在处理第i个
  2. 边界情况是吃没吃饭,我们需要一维变量来表示i以及i后7的个人(因为i最多只能影响之后7个人)是否吃饭
  3. 由于做饭时间与上一个吃饭的人有关,我们还需要一维变量来存储上一个拿到饭菜的人相对于i的位置k,k属于[-8,7](当k=0时表示其本身)

综上我们设:f[i][st][k]:表示前i-1给人已经吃完了,i以及i后面七个人的吃饭状态是st,上一次吃饭的人的位置与i的偏移是k,的最短时间
例如:st=(00000011)(2进制下),表示第i个和第i+1个吃了,其他没吃
f初始化为正无穷,初始状态为 :f[1][0][7]= 0;
为什么f[1][0][7]为初始状态,我认为k=7表示第0位,而我们一上来就要更新第1个人,所以需要第0个人的状态。

现在我们开始更新状态,
如果第i个人吃饭了,那我们可以考虑转移到第i+1个人,即j&1==1(也就是j的第一位是1),此时i后面7个人的吃饭顺序就不会再受到 i的影响了,因为他们不可能插队到i的前面。此时转移为:
f[i+1][j>>1][k-1]=min(f[i][j>>1][k-1],f[i][j][k])
j>>1是因为j是相对于当前选定对象的偏移量,对于i来说是j,那对于第i+1个人,j就要左移一位,k也同理

如果第i个人没吃饭,没办法转移到i+1,(因为i+1之前的人还没吃完饭)。此时我们需要从i以及i之后的7位中选出一个人来打饭,也就是枚举l从0到7,此时转移方程为:
f[i][j | (1 << l)][l + 8]= min(f[i][j | (1 << l)][l + 8], f[i][j][k + 8] + Time(a[i + k].t, a[i + l].t));
Time是计算做饭时间,i+k是上一个打饭的人,i+l是当前要打饭的人,当然如果i+l是第一个打饭的人,Time就是0,否则就是题目所说的计算值
注意:每个人都有自己的忍耐范围,也就是并不是所有人都能接收自己后面7个人,所有我们要对于每个人,如果超出了忍耐范围,我们就不考虑这个人。

代码:

// Problem: P2157 [SDOI2009]学校食堂
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2157
// Memory Limit: 125 MB
// Time Limit: 800 ms
// Data:2021-08-12 13:00:56
// By Jozky#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
template <typename T> inline void read(T& x)
{T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f;
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#elsestartTime= clock();freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
int f[1004][1 << 9][20];
struct node
{int t, b;
} a[1030];
int base= 8; //偏移量
int Time(int x, int y)
{return (x | y) - (x & y);
}
int main()
{//rd_test();int t;read(t);while (t--) {int n;read(n);for (int i= 1; i <= n; i++) {read(a[i].t);read(a[i].b);}memset(f, INF_int, sizeof(f));f[1][0][7]= 0; //?/*f[i+1][j<<1][k-1]=min(f[i+1][j<<1][k-1],f[i][j][k]);//i+k是上一次打饭的人,i+h是枚举本次打饭的人f[i][j|(1<<h)][h]=min(f[i][j|(1<<h)][h],f[i][j][k]+Time(i+k,i+h));*/for (int i= 1; i <= n; i++) { //对于第i个人已经吃饭for (int j= 0; j < (1 << 8); j++) { //从自己开始往后8个人的状态for (int k= -8; k <= 7; k++) { //上一次吃饭的人距离i的位置if (f[i][j][k + 8] != INF_int) {if (j & 1) { //j的第一位是1,说明i本身吃饭了f[i + 1][j >> 1][(k + base) - 1]= min(f[i + 1][j >> 1][(k + base) - 1], f[i][j][k + base]);}else { //如果第i个还未吃饭,枚举它后面的人int lim= INF_int;for (int l= 0; l < 8; l++) {if (!(j & (1 << l))) //如果第l个人吃饭了{if (i + l > lim)break;lim= min(lim, i + l + a[i + l].b);if (i + k) //不是第一个吃饭的{f[i][j | (1 << l)][l + base]= min(f[i][j | (1 << l)][l + base], f[i][j][k + base] + Time(a[i + k].t, a[i + l].t));}else //第一个吃饭的{f[i][j | (1 << l)][l + base]= min(f[i][j | (1 << l)][l + base], f[i][j][k + base] + 0);}}}}}}}}int res= INF_int;for (int k= 0; k <= 8; k++) {res= min(res, f[n + 1][0][k]);}printf("%d\n", res);}//Time_test();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316419.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EntityFramework Core 3.0 Preview

前段时间.Net Core 3.0 发布了&#xff0c;Entity Framework Core 3.0 也发布了Preview版。假期用了一上午大致研究了一遍&#xff0c;同时又体验了一把Visual Studio 2019。总结一下分享给大家&#xff1a;VS2019 新建.Net Core 3.0 Console应用&#xff0c;添加EFCore相关的N…

[luogu-P4299] 首都(并查集 + LCT动态维护树的重心 / 维护虚儿子信息)

problem luogu-P4299 solution 本题考察了很经典的模型&#xff0c;运用了很经典的解法。 本题用到了重心的两个性质&#xff1a; 两棵树合并为同一棵树时&#xff0c;新的重心一定在原来两棵树各自重心的路径上。 重心为根时的最大子树大小最小&#xff0c;不超过 siz/2s…

计算几何模板中的代码

计算几何模板代码选自kuangbin 7 计算几何 7.1 二维几何 // 计算几何模板 const double eps 1e-8; const double inf 1e20; const double pi acos(-1.0); const int maxp 1010; //Compares a double to zero int sgn(double x){if(fabs(x) < eps)return 0;if(x < …

机器学习 ML.NET 发布 1.0 RC

ML.NET 是面向.NET开发人员的开源和跨平台机器学习框架&#xff08;Windows&#xff0c;Linux&#xff0c;macOS&#xff09;,通过使用ML.NET,.NET开发人员可以利用他们现有的工具和技能组&#xff0c;为情感分析&#xff0c;推荐&#xff0c;图像分类等常见场景创建自定义机器…

[PA2015]Siano(线段树 + 二分)

problem luogu-P5579 solution 此题关键在于发现一个结论&#xff1a;生长速度快的草在任何时刻都不可能矮于生长速度慢的草。 正确性显然。 所以当我们将草按照 aaa 升序排序后&#xff0c;每次收割的草一定是一个后缀。 那么这个后缀的起点就可以二分找到。 割完后要对…

容器化时代我们应当选择Kubernetes

昨天发的文章《基于Kubernetes 构建.NET Core 的技术体系》&#xff0c;有同学问.NET Core上有Spring Cloud类似的平台吗&#xff1f; .NET Core出现这么久了&#xff0c;这个为云原生应用开发而准备的系统需要Spring cloud这样的全家桶吗&#xff1f; 大家希望使用Spring Clou…

2021杭电第8场

2021杭电第8场 题号题目知识点HDU 7056X-liked CountingHDU 7057Buying SnacksHDU 7058Ink on paperHDU 7059Counting StarsHDU 7060Separated NumberHDU 7061GCD GameHDU 7062A Simple ProblemHDU 7063Square CardHDU 7064Singing SuperstarHDU 7065Yinyang

[ZJOI2015]幻想乡 Wi-Fi 搭建计划(dp + 结论)

problem luogu-P3344 solution 这个题面&#xff0c;这个数据范围&#xff0c;完完全全就是网络流宗教。。然而我发现建不出来。 很多一眼网络流最后却不是网络流而往往是 dpdpdp 的题目都有一个特性&#xff1a;一个点可以流出多条流量&#xff0c;流入流量却只能为 111。…

CefSharp中c#和JavaScript交互读取电脑信息

介绍CEF是由Marshall Greenblatt于2008年创建的基于Google Chromium的BSD许可开源项目。与主要关注谷歌Chrome应用程序开发的Chromium项目本身不同&#xff0c;CEF专注于在第三方应用程序中促进嵌入式浏览器用例。CEF通过提供生产质量稳定的API&#xff0c;发布跟踪特定Chromiu…

Ink on paper HDU - 7058

Ink on paper HDU - 7058 题意&#xff1a; 给出n个墨水的初始位置&#xff0c;每秒向外扩展0.5cm&#xff0c;显示一个圆圈&#xff0c;问所有墨水连接起来需要多长时间 题解&#xff1a; 很明显&#xff0c;在完全图中找最小生成树&#xff0c;并记录最小生成树中最长的边…

加与乘(博弈论)

problem A,BA,BA,B 在玩游戏&#xff0c;给定一排长度为 nnn 的数列&#xff0c;每个人轮流取出任意一对相邻的两个数&#xff0c;然后把两个数的和或者乘积放入。 TTT 组询问。每组给定 n,mn,mn,m&#xff0c;接下来给定长度为 nnn 的数列 aia_iai​。 m0m0m0 AAA 先操作&…

C#8.0可空引用类型的使用注意要点

最近VS2019正式版发布了&#xff0c;装下来顺便试用了一下C#8.0&#xff0c;最大的看点应该就是可空引用类型了。不过C#8.0仍然处于Beta的状态&#xff0c;而且试用时也遇到了几个坑。背景知识说明&#xff1a;所谓的可空引用类型是指&#xff0c;一旦启用了可空引用类型这个新…

Singing Superstar HDU - 7064

Singing Superstar HDU - 7064 题意&#xff1a; 问在串T中出现了几次不相交的串S&#xff1f; 每次有n个串S询问 题解&#xff1a; AC自动机板子题。。 直接上模板 代码&#xff1a; #include <bits/stdc.h> #include <unordered_map> #define debug(a, b) …

ASP.NET Core Web 项目文件介绍

ASP.NET Core Web 项目文件在本视频中&#xff0c;我们将探索并了解asp.net core项目文件。 我们使用C&#xff03;作为编程语言&#xff0c;因此项目文件具有.csproj扩展名。如果您使用过以前版本的ASP.NET&#xff0c;那么您可能对此文件非常熟悉&#xff0c;但此文件中包含的…

[ZJOI2016] 小星星(树型dp + 状压dp + 容斥)

problem luogu-P3349 solution 这个数据首先就能想到状压 dpdpdp。 先考虑在树上的朴素 dp(i,j,S):dp(i,j,S):dp(i,j,S): 节点 iii 的对应原图编号为 jjj&#xff0c;其子树对应的编号构成的点集为 SSS 的方案数。 需要满足两个限制条件&#xff1a; 原图的每个节点只能被…

GCD Game HDU - 7061

GCD Game HDU - 7061 题意&#xff1a; 有n个数ai&#xff0c;两个人轮流操作&#xff0c;每次选择一个数ai&#xff0c;再人选一个x(1<x<ai)&#xff0c;然后用gcd(ai,x)代替ai 谁先不能操作谁先输掉比赛 题解&#xff1a; 第一反应nim游戏&#xff0c;gcd是取最大公…

[ZJOI2016]旅行者(网格图分治最短路)

problem luogu-P3350 solution 据说&#xff0c;网格图最短路用分治是一个人人皆知的套路。对不起我不是人 类比整体二分的算法流程。 考虑在一个 (xl,yl)−(yl,yr)(xl,yl)-(yl,yr)(xl,yl)−(yl,yr) 矩阵内处理 [ql,qr][ql,qr][ql,qr] 的询问。 以矩阵的中界线 mid\text{…

DotNetCore 3.0 助力 WPF 开发

前言Visual Studio 2019 已经正式发布了&#xff0c;DotNetCore 3.0 的正式版也指日可待。在之前的版本中&#xff0c;作为一名基于微软生态的传统 WPF 程序员看着隔壁同学在开发 DotNetCore 网站时用着各种特性好生羡慕&#xff0c;想着巨硬啥时候能让客户端开发者也能尝尝甜头…

H - Square Card HDU - 7063

H - Square Card HDU - 7063 题意&#xff1a; 有两个圆形区域&#xff0c;一个是得分区域&#xff0c;一个是获得奖金区域&#xff0c;现在你有一个边长为a的正方形,当正方形在如果在某一时刻它严格在圆形范围内&#xff0c;才算合法。 问把牌扔到任意的位置被得分和同时获得…

【刷题记录】排列dp

文章目录[AtCoder-ABC209-f] Deforestation[AtCoder-Educational DP Contest-T]Permutation「JOI Open 2016」摩天大楼topcoder srm 489 div1 lev3 : AppleTrees[CodeForces-626F] Group Projects[TopCoder] Seatfriends小结[AtCoder-ABC209-f] Deforestation 考虑相邻的两棵树…