状压DP之学校食堂
题目
传送们
小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭。学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴。当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数表示。 由于人手不够,食堂每次只能为一个人做菜。做每道菜所需的时间是和前一道菜有关的,若前一道菜的对应的口味是a,这一道为b,则做这道菜所需的时间为(a or b)-(a and b),而做第一道菜是不需要计算时间的。其中,or 和and 表示整数逐位或运算及逐位与运算,C语言中对应的运算符为“|”和“&”。
学生数目相对于这个学校还是比较多的,吃饭做菜往往就会花去不少时间。因此,学校食堂偶尔会不按照大家的排队顺序做菜,以缩短总的进餐时间。
虽然同学们能够理解学校食堂的这种做法,不过每个同学还是有一定容忍度的。也就是说,队伍中的第i 个同学,最多允许紧跟他身后的Bi 个人先拿到饭菜。一旦在此之后的任意同学比当前同学先拿到饭,当前同学将会十分愤怒。因此,食堂做菜还得照顾到同学们的情绪。 现在,小F 想知道在满足所有人的容忍度这一前提下,自己的学校食堂做完这些菜最少需要多少时间。
输入格式
第一行包含一个正整数C,表示测试点的数据组数。 每组数据的第一行包含一个正整数N,表示同学数。 每组数据的第二行起共N行,每行包含两个用空格分隔的非负整数Ti和Bi,表示按队伍顺序从前往后的每个同学所需的菜的口味和这个同学的忍受度。 每组数据之间没有多余空行。
输出格式
包含C行,每行一个整数,表示对应数据中食堂完成所有菜所需的最少时间。
输入输出样例
输入
2
5
5 2
4 1
12 0
3 3
2 2
2
5 0
4 0
输出
16
1
思路
设dp[i][j][k]表示第1到第i-1个人已经打到饭,i以及后面7个人的状态为j,最后一个打饭的编号为i+k,(k的范围是-8到7),那么我们分析转移
- 第i个人已经打完饭,那么i后面的7个人只能在i后面打饭(i:我打完了,你们随意),那么可以直接更新i+1的状态
dp[i+1][j>>1][k-1]=min(dp[i+1][j>>1][k-1],dp[i][j][k]);
- i并没有打完饭,这时候并不是简单的枚举i后面的b[i]个人,而是向后找忍耐度+其位置的最小值,因为每个人的忍耐度是不一样的,就比如i的忍耐读是5,而i+1是1,那么只能是i后面两个人可以在i前面打饭,所以要考虑忍耐距离,枚举i后面7个人,在满足该条件下可以进行转移,
dp[i][j|(1<<h)][h+8]=min(dp[i][j|(1<<h)][h+8],dp[i][j][k+8]+(i+k?(t[i+k]^t[i+h]):0));
- 一点细节,k的范围是-8到7,所以存的时候要都加一下8,保证数组不越界(段错误警告)。
- (Ai or Ai+1)−(Ai and Ai+1) = Ai xor Ai+1
附上代码
#include<bits/stdc++.h>
using namespace std;
int T;
const int maxn=1000+10;
const int N=1<<8;
const int inf=0x7f7f7f7f;
int dp[maxn][N][20];
int t[maxn],b[maxn],n;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
int main(){
T=read();
while(T--){
memset(t,0,sizeof(t));//记得初始化
memset(b,0,sizeof(b));
n=read();
for(int i=1;i<=n;i++){
t[i]=read();
b[i]=read();
}
memset(dp,0x7f,sizeof(dp));//初始化无穷大
dp[1][0][7]=0;//第0个人已经打完,上一个打饭的人是7-8(不存在)
for(int i=1;i<=n;i++){
for(int j=0;j<(1<<8);j++){
for(int k=-8;k<=7;k++){
if(dp[i][j][k+8]!=inf){//除去效操作
if(j&1)dp[i+1][j>>1][k+7]=min(dp[i+1][j>>1][k+7],dp[i][j][k+8]);
else{
int lim=inf;//设定边界
for(int h=0;h<=7;h++){
if(!((j>>h)&1)){
if(i+h>lim)break;超过最大边界,不能转移
lim=min(lim,i+h+b[i+h]);
dp[i][j|(1<<h)][h+8]=min(dp[i][j|(1<<h)][h+8],dp[i][j][k+8]+(i+k?(t[i+k]^t[i+h]):0));//i+k==0,无需等待
}
}
}
}
}
}
}
int ans=inf;
for(int k=0;k<=8;k++){
ans=min(ans,dp[n+1][0][k]);
}
cout<<ans<<endl;
}
}
状压DP之学校食堂的更多相关文章
- bzoj 1226 [SDOI2009]学校食堂Dining(状压DP)
Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以 ...
- BZOJ 1226 学校食堂(状压DP)
状压DP f(i,j,k)表示前i−1个人已经吃了饭,且在i之后的状态为j的人也吃了饭(用二进制表示后面的状态),最后吃的那个人是i之后的第k个 (注意k可以是负数) 然后 如果j&1=1那么 ...
- [luoguP2157] [SDOI2009]学校食堂Dining(状压DP)
传送门 这种鬼畜的状压DP...第一次见 看到 0 <= Bi <= 7 就应该想到状态压缩,然而此题实在太鬼畜,想到也没什么乱用 f[i][j][k]表示前i-1个人全部吃完,i~i+7 ...
- [学习笔记]状压dp
状压 \(dp\) 1.[SDOI2009]Bill的挑战 \(f[i][j]\) 表示匹配到字符串的第 \(i\) 位状态为 \(j\) 的方案数 那么方程就很明显了,每次枚举第 \(i\) 位的字 ...
- 状压DP之LGTB 与序列
题目 思路 这道题竟然是状压DP,本人以为是数论,看都没看就去打下一题的暴力了,哭 \(A_i\)<=30,所以我们只需要考虑1-58个数,再往后选的话还不如选1更优,注意,1是可以重复选取的, ...
- [欢乐赛]班服 状压DP
班服 (shirt.pas/.c/.cpp) 时间限制:1s:内存限制 128MB 题目描述: 要开运动会了,神犇学校的n个班级要选班服,班服共有100种样式,编号1~100.现在每个班都挑出了一些样 ...
- 【vijos】1286 座位安排(状压dp)
https://vijos.org/p/1286 这题好神不会捉... 首先我们知道所有情况有C(n*m, k)种,这个好搞.但是两两不相邻这个有点难搞.. 原来是状压dp..sigh. 设状态f[i ...
- [luoguP3694] 邦邦的大合唱站队/签到题(状压DP)
传送门 来自kkk的题解: 70分做法:枚举每个学校顺序,暴力. 100分:状压dp.从队列头到尾DP, 状态:f[i]表示i状态下最小的出列(不一致)的个数. 比如f[1101]表示从头到位为1/3 ...
- 状压DP UVA 10817 Headmaster's Headache
题目传送门 /* 题意:学校有在任的老师和应聘的老师,选择一些应聘老师,使得每门科目至少两个老师教,问最少花费多少 状压DP:一看到数据那么小,肯定是状压了.这个状态不好想,dp[s1][s2]表示s ...
随机推荐
- MAC抓包工具Charles安装及破解
参考资料:https://juejin.im/post/5c0a430f51882516207d205d 下载 Charles官网下载安装包,下载成功后根据指示安装即可 官网地址:http://www ...
- 用Java模拟游戏重力的实现(弹跳)
年末开了Java实训大作业 想了好几天决定选择马里奥小游戏 发现即使做出来但是跳跃功能是很“笨拙”的,和我们玩的游戏不一样,没有跳跃速度的快慢什么的,后来才知道这个叫做游戏里面重力的模拟. 组队做系统 ...
- Flutter 中 GestureDetector 的使用误区
在实际开发中,我们通常需要实现某个组件的更多点击事件.比如:原生的RaisedButton组件是无法响应诸如拖拽或是按下.抬起等细化的动作,它只有一个onPressed()方法来表示.当我们想实现这些 ...
- 获取随机User-Agent的请求头
''' 获取随机User-Agent的请求头 ''' import random #用户代理User-Agent列表 USER_AGENTS = [ "Mozilla/5.0 (Macint ...
- SpringCloud(一)版本选择
Springboot版本 官网:https://spring.io/projects/spring-boot 在官网上 springboot已经更新到最新2.2.6 Spingcloud版本 官网:h ...
- Cookie的简介与使用
Cookie 历来指就着牛奶一起吃的点心.然而,在因特网内,"Cookie"这个字有了完全不同的意思.那么"Cookie"到底是什么呢?"Cookie ...
- oracle自定义split分割函数
函数如下: create or replace FUNCTION fn_rme_split(p_str IN VARCHAR2, p_delimiter IN VARCHAR2) RETURN rme ...
- 微服务配置中心 Apollo 源码解析——Admin 发送发布消息
内容参考:https://www.toutiao.com/a6643383570985386509/ 摘要: 原创出处http://www.iocoder.cn/Apollo/admin-server ...
- web安全中的session攻击
运行着个简单的demo后,打开login.jsp,使用firebug或chrome会发现,即使没有登录,我们也会有一个JSESSIONID,这是由服务器端在会话开始是通过set-cookie来设置的匿 ...
- trollcave解题
这是第一次完整地进行模拟渗透,前前后后一共花了一天时间,花了点时间写了个writeup. 博主是个菜鸡,如果有大神看到,请轻喷...... writeup下载:https://hrbeueducn-m ...