【BZOJ1226】[SDOI2009] 学校食堂
题目描述
小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
说明
对于第一组数据:
同学1允许同学2或同学3在他之前拿到菜;同学2允许同学3在他之前拿到菜;同学3比较小气,他必须比他后面的同学先拿菜……
一种最优的方案是按同学3、同学2、同学1、同学4、同学5做菜,每道菜所需的时间分别是0、8、1、6及1。
【数据规模和约定】
对于30%的数据,满足1 ≤ N ≤ 20。
对于100%的数据,满足1 ≤ N ≤ 1,000,0 ≤ Ti ≤ 1,000,0 ≤ Bi ≤ 7,1 ≤ C ≤ 5。
存在30%的数据,满足0 ≤ Bi ≤ 1。
存在65%的数据,满足0 ≤ Bi ≤ 5。
存在45%的数据,满足0 ≤ Ti ≤ 130。
有点难度的状态压缩DP呢,一开始真的一直想不到状态转移的方法。
(别告诉我你完全没有想到状态压缩,B[i]才7诶!)
一个人既和前面的人有关系,又和后面的人有关系,真是没法转移了。。。
但是总归是有办法的
我们开一个DP数组
f[i][st][k]
表示此时考虑到第 i 个人,从第i个人开始(包括他自己)后面七个人的吃饭状态是st(1表示吃了,0表示没吃),前一个吃饭的人与i的距离为k(因而k的范围就是 [-8,7]对吧^.^)所用时间的最小值。
所以此时的第i个人不一定吃了哦。
思考下面两种情况:
1. 此时枚举到的i,已经吃过了(st里i对应的位置就为1),那么后面的人不管按什么顺序吃,i都不会生气。
所以这时可以直接更新i+1的状态即 f[i+1][st>>1][k-1]=min(f[i+1][st>>1][k-1],f[i][st][k])
(向后移一个人,st要右移,前一个吃完的人离i+1的距离变成k-1)
(i同学:“你们爱咋咋,反正我已经吃完了,i+1同学,我可以直接更新你的状态了。”)
2.此时枚举到的i,还没有吃饭 ,那么他最多只能忍受后面B[i]个人比他先吃到饭,所以这时候就可以枚举从i开始后面的人谁先吃饭了。
所以此时用lx来枚举后面的人(0<=lx<=7),f[i][ st|tw[lx] ] [lx]=min(f[i][st][k]+Time(i+k,i+lx),f[i][ st|tw[lx] ][lx])
不过还要注意后面的人的B[i+lx]的值是不一样的,我们要开一个变量rx来记录最右能枚举到的lx,并随时更新rx(不然会有很多人生气的!),当lx>rx时, 适时地break就可以了。
(i同学:“我还没吃饭!我后面B[i]个人后的人谁敢先吃饭,我就让你WA”)
最后的答案当然就存在 f[n][1][k]里啦 (-8<=k<=0)
B[i]最多只会有7,而n也才1000,复杂度是很优秀的呢。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> #define For(i,a,b) for(register int i=a;i<=b;++i)
#define Re register
#define inf 0x7f7f7f
#define Nm(i) i+8
#define Pn putchar('\n') using namespace std;
const int N=1e3+,ST=(<<)+;
int f[N][ST][];
int n,m,T[N],B[N],tw[],nf; inline void read(int &v){
v=;
char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')v=v*+c-'',c=getchar();
}
void write(int x){
if(x>)write(x/);
int xx=x%;
putchar(xx+'');
}
int TM(int x,int y){
if(x==)return ;
return T[x]^T[y];
} int main(){
freopen("dining.in","r",stdin);
freopen("dining.out","w",stdout);
int Tx; read(Tx);
For(i,,)tw[i]=<<i;
while(Tx--){
read(n);
For(i,,n) read(T[i]),read(B[i]); memset(f,inf,sizeof(f));
nf=f[][][];
T[]=B[]=; f[][][Nm(-)]=;
For(i,,n) For(st,,tw[]-) For(k,-,){
int Fx=f[i][st][Nm(k)];
if(Fx==nf)continue;
//cout<<Fx<<endl;
if(st&){
f[i+][st>>][Nm(k-)]=min(f[i+][st>>][Nm(k-)],Fx);
}else{
int mxR=nf;
For(lx,,){
if(st&tw[lx])continue;
if(i+lx>mxR)break;
mxR=min(mxR,i+lx+B[i+lx]); f[i][ st|tw[lx] ][ Nm(lx) ] =min( f[i][ st|tw[lx] ][ Nm(lx) ],Fx+TM(i+k,i+lx) ); }
}
}
int fn=nf;
For(i,-,)fn=min(fn,f[n][][Nm(i)]);
write(fn); Pn;
}
fclose(stdin); fclose(stdout);
return ; }
求资瓷~
【BZOJ1226】[SDOI2009] 学校食堂的更多相关文章
- BZOJ1226 [SDOI2009]学校食堂Dining 【状压dp】
题目 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数表示 ...
- BZOJ1226 SDOI2009学校食堂(状压dp)
由于Bi<=7,考虑状压. 如果考虑前i个位置的话,状态里需要压入前7个人后7个人,显然是跑不动的. 那么改成考虑前i个人.于是设f[i][j][k]表示前i个人都已吃完饭,i+1后面7个人的吃 ...
- BZOJ1226: [SDOI2009]学校食堂Dining
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1226 状压dp. f[i][s][k]表示原顺序中前i-1个人都吃了饭,当前状态为s(i及i之 ...
- bzoj千题计划286:bzoj1226: [SDOI2009]学校食堂Dining
http://www.lydsy.com/JudgeOnline/problem.php?id=1226 关键点:一个人只能忍受 ‘紧跟’ 在他 后面的b个人比他先打到饭 dp[i][j][k] 前i ...
- BZOJ1226 SDOI2009学校食堂
这题状压DP太神了. g[i][j][k]表示前i-1个人都已打到饭,自己和后七个人打饭的情况是j,当前最后一个打饭的与i的关系是k 如果j&1==1说明当前这个人也打了饭,那么可以转移到g[ ...
- 【BZOJ1226】[SDOI2009]学校食堂Dining 状压DP
[BZOJ1226][SDOI2009]学校食堂Dining Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满 ...
- BZOJ 1226: [SDOI2009]学校食堂Dining
1226: [SDOI2009]学校食堂Dining Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 730 Solved: 446[Submit][ ...
- 【题解】Luogu P2157 [SDOI2009]学校食堂
原题传送门:P2157 [SDOI2009]学校食堂 一看题目就知道是状压dp 设f[i][j][k]表示第1到i-1个人都吃完了饭,第i个人以及后面的7个人是否打饭的状态为j,当前最后打饭的人的编号 ...
- 【BZOJ1226】学校食堂(动态规划,状态压缩)
[BZOJ1226]学校食堂(动态规划,状态压缩) 题面 BZOJ 洛谷 题解 发现\(b\)很小,意味着当前这个人最坏情况下也只有后面的一小部分人在他前面拿到饭. 所以整个结果的大致顺序是不会变化的 ...
- 【bzoj1226】【[SDOI2009]学校食堂Dining】状压dp
(上不了p站我要死了,侵权度娘背锅) Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人 ...
随机推荐
- Flow 的工作方式 类型检查
Vue.js 技术揭秘 | Vue.js 技术揭秘 https://ustbhuangyi.github.io/vue-analysis/ Vue技术内幕 http://hcysun.me/vue-d ...
- Conditions in bash scripting (if statements)
Shell中判断语句if中-z至-d的意思 - sunny_2015 - 博客园 https://www.cnblogs.com/coffy/p/5748292.html Conditions in ...
- Windows平台,开机自动运行应用
打开注册表编辑器(Win+R后执行regedit) 进入HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 新建字符串值, ...
- ./autogen.sh: 4: autoreconf: not found
./autogen.sh: 4: autoreconf: not found 是在不同版本的 tslib 下执行 autogen.sh 产生.它们产生的原因一样,是因为没有安装 automake ...
- ps 工具栏使用
1:称动工具,快捷键是v,则选中移动工具:按shift和左键,可移动当前层移到另一层的中间对齐.如果不用sfhift键,则只是移动:alt+左键上移动,则复制层:alt+中间滚轮,则为放大和缩小. 2 ...
- underscore.js中模板函数应用
一.使用技术要点 (1)使用zepto.js的ajax请求; (2)使用underscore.js的_.template设定模板,模板一般以<script type="text/tem ...
- elasticsearch 中文分词(elasticsearch-analysis-ik)安装
elasticsearch 中文分词(elasticsearch-analysis-ik)安装 下载最新的发布版本 https://github.com/medcl/elasticsearch-ana ...
- Android Developers - Training
Recently I've been contemplating to create a new App with the true "Android Design",new An ...
- HiddenHttpMethodFilter
操作步骤: 在web.xml中配置: 删除操作: 其他操作即为将DELETE换成INPUT/POST/GET
- Field 'CID' doesn't have a default value
解决:在数据库客户端navicat中设计表勾选自动递增