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();
}

P2157 [SDOI2009]学校食堂相关推荐

  1. [SDOI2009]学校食堂

    前言:经过AC这道题的过程,让我明白了一点,不要过于相信您的同伴(因为他会让您的代码wa一天还不清楚为什么).---上述观点均由StarTrek大佬背锅 题目描述 原题链接:[SDOI2009]学校食 ...

  2. [SDOI2009]学校食堂Dining 洛谷p2157

    题目描述 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数 ...

  3. [SDOI2009]学校食堂(状态压缩)

    题目描述 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数 ...

  4. 【BZOJ1226】[SDOI2009] 学校食堂

    题目描述 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数 ...

  5. [SDOI2009]学校食堂Dining

    Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以 ...

  6. [SDOI2009]学校食堂Dining(洛谷2157)

    标签:状压DP,bitset位运算 题目描述 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同 ...

  7. BZOJ 1226 [SDOI2009] 学校食堂Dining

    Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以 ...

  8. BZOJ 1226: [SDOI2009]学校食堂Dining [DP 状压]

    题意: $n$个人排队打饭,第$i$个人口味$a_i$,能容忍最多身后第$b_i$个人先打饭. 先后两人$i,j$做饭时间为$a_i & a_j - a_i | a_j$ 求最少时间 一开始想 ...

  9. BZOJ1226 SDOI2009学校食堂(状压dp)

    由于Bi<=7,考虑状压. 如果考虑前i个位置的话,状态里需要压入前7个人后7个人,显然是跑不动的. 那么改成考虑前i个人.于是设f[i][j][k]表示前i个人都已吃完饭,i+1后面7个人的吃 ...

最新文章

  1. Naive Operations (线段树 分析复杂度)
  2. windows下安装Python virtualenvwrapper-win
  3. C语言sprintf 和 sscanf函数
  4. 在猜年龄的基础上编写登录、注册方法,并且把猜年龄游戏分函数处理
  5. flume案例-flume级联-组件分析
  6. 判断一个java对象中的属性是否都未赋值_100道Java基础面试题(一)
  7. 触发器 REFERENCING OLD AS OLD NEW AS NEW FOR EACH Row
  8. 有小数点是什么类型_「JAVA零基础入门系列」Day3 Java基本数据类型
  9. 以鶸ice为例,手撸一个解释器(一)明确目标
  10. C++---模板特化
  11. python predict_对Keras中predict()方法和predict_classes()方法的区别说明
  12. CSRF verification failed. Request aborted.的解决办法
  13. 阶段3 1.Mybatis_01.Mybatis课程介绍及环境搭建_06.mybatis的环境搭建
  14. .net reactor 学习系列(四)---.net reactor应用场景
  15. clion使用之如何在编译运行多个程序(以cpp为例)
  16. Arduino米思齐Mixly---人体声控灯
  17. 什么是知识库管理系统?如何搭建企业知识库系统?
  18. 用收敛标准计算神经网络迭代次数
  19. 关于数字证书链的一点认知
  20. 【数据库】国土空间规划数据库(全域)_模板空库

热门文章

  1. 来自女朋友的灵魂拷问!| 今日最佳
  2. 每日一笑 | 一些关于集合的知识
  3. android+清除循环动画,android - 如何使用ViewPropertyAnimator生成循环动画?
  4. 在java中写出html代码,在java里写html代码
  5. 针对Spring的Spring Retry 我发现了这样一个大家都不知道的技巧!
  6. linux怎么搜索特定文件夹,linux如何在特定文件夹中查找特定文件
  7. mysql特性举例_MySQL事务的四大特性和隔离级别
  8. sm缩写代表什么意思_pe、PE在电气有代表什么意思,你发现没有,电气技术很有意思...
  9. aes算法实现c语言_以C语言实现归并排序为例,谈谈五大常用算法之一的“分治法”...
  10. 数字图像处理王伟强_深度学习主导下,还有必要学数字图像处理?