Solution

比较好想的dp, 但是坑不少QAQ, 调半天

由于容忍度 $b_i$<= 7, 所以可以考虑将第$i$个人接下来的$b_i$ 个人作为一个维度记录状态。

于是我们定义数组$f[ i ][ S ]$ 表示前$i-1$个人都已经拿到了菜, S表示$i$和接下来$b_i$个人是否拿到了菜。

然后依次枚举$i$ :第$i$个人, $S$ : $i$与接下来$b_i$个人是否拿到菜, $nt$ : 下一次谁拿菜, $fr$ : 上一次谁拿菜

还需要通过$judge$来判断该状态是否可行, 最后进行$dp$

具体看代码里的$jud$ 和$dp$ 函数

Code

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define rd read()
#define rep(i,a,b) for(register int i = (a); i <= (b); ++i)
#define per(i,a,b) for(register int i = (a); i >= (b); --i)
using namespace std; const int N = 1e3 + ;
const int base = ;
const int inf = ; int tas[N], bac[N], f[N][][];
int n, T; int read() {
int X = , p = ; char c = getchar();
for(; c > '' || c < ''; c = getchar()) if(c == '-') p = -;
for(; c >= '' && c <= ''; c = getchar()) X = X * + c - '';
return X * p;
} int jud(int now, int S, int nt, int fr) {
if(f[now][S][fr +base] >= inf) return ;
if((S >> nt) & ) return ;
if(!((S >> fr) & ) && fr >= ) return ;
if(now + fr < ) return ;
rep(i, now, now + nt) if(!((S >> (i - now)) & ) && now + nt > i + bac[i]) return ;
return ;
} void dp(int now, int S, int nt, int fr) {
int ntS = S | ( << nt), tmp = inf; //ntS表示给nt拿完菜的状态
if(now + fr) tmp = min(tmp, f[now][S][fr + base] + (tas[now + nt] ^ tas[now + fr]));
else tmp = min(tmp, f[now][S][fr + base] + );
nt += now;
for(; ntS & ; ntS >>= ) {
f[now][ntS][nt - now + base] = min(f[now][ntS][nt - now + base], tmp);
//printf("%d %d %d\n", now, ntS, nt);
now++;
}
f[now][ntS][nt - now + base] = min(f[now][ntS][nt - now + base], tmp);
//printf("%d %d %d\n", now, ntS, nt);
} void work() {
memset(f, , sizeof(f));
n = rd;
rep(i, , n) tas[i] = rd, bac[i] = rd;
f[][][- + base] = ;
rep(i, , n) rep(j, , ( << (bac[i] + )) - ) rep(k, , bac[i]) rep(fr, -, ) {//fr必须从-8枚举
if(!jud(i, j, k, fr)) continue;
dp(i, j, k, fr);
}
int ans = inf;
rep(i, -, ) ans = min(ans, f[n][][i + base]);
printf("%d\n", ans);
} int main()
{
T = rd;
rep(i, , T) work();
}

Luogu 2157 [SDOI2009]学校食堂 - 状压dp的更多相关文章

  1. P2157 [SDOI2009]学校食堂 状压DP

    题意: 排队买饭,时间为前一个人和后一个人的异或和,每个人允许其后面B[i] 个人先买到饭,问最少的总用时. 思路: 用dp[i][j][k] 表示1-i-1已经买好饭了,第i个人后面买饭情况为j,最 ...

  2. BZOJ 1226 学校食堂(状压DP)

    状压DP f(i,j,k)表示前i−1个人已经吃了饭,且在i之后的状态为j的人也吃了饭(用二进制表示后面的状态),最后吃的那个人是i之后的第k个 (注意k可以是负数) 然后 如果j&1=1那么 ...

  3. bzoj1226/luogu2157 学校食堂 (状压dp)

    我们先约定:(左) 窗口_人人人人人 (右) 可以发现,我们只需要知道最靠左的还没打饭的人 以及它身后7个人的状态 以及上一个打饭的人是谁 因为他左面的就都打过了 右面7个人以后肯定还没打 可以设f[ ...

  4. SDOI 2009 学校食堂 状压dp

    这个题的关键处1 紧跟着他的bi个人 —— 由此得出任意一个状态都可以表示为 有第一个人没吃到饭做分隔的前面所有人已吃饭,并用1<<8表示之后的(包括他)的八个人的状态2 信息仍然是上一个 ...

  5. 【题解】Luogu P2157 [SDOI2009]学校食堂

    原题传送门:P2157 [SDOI2009]学校食堂 一看题目就知道是状压dp 设f[i][j][k]表示第1到i-1个人都吃完了饭,第i个人以及后面的7个人是否打饭的状态为j,当前最后打饭的人的编号 ...

  6. BZOJ1226或洛谷2157 [SDOI2009]学校食堂

    BZOJ原题链接 洛谷原题链接 注意到\(B[i]\)很小,考虑状压\(DP\). 设\(f[i][j][k]\)表示前\(i - 1\)个人已经拿到菜,第\(i\)个人及其后面\(7\)个人是否拿到 ...

  7. [学习笔记]状压dp

    状压 \(dp\) 1.[SDOI2009]Bill的挑战 \(f[i][j]\) 表示匹配到字符串的第 \(i\) 位状态为 \(j\) 的方案数 那么方程就很明显了,每次枚举第 \(i\) 位的字 ...

  8. 洛谷 P3112 后卫马克 —— 状压DP

    题目:https://www.luogu.org/problemnew/show/P3112 状压DP...转移不错. 代码如下: #include<iostream> #include& ...

  9. 洛谷 3112 [USACO14DEC]后卫马克Guard Mark——状压dp

    题目:https://www.luogu.org/problemnew/show/P3112 状压dp.发现只需要记录当前状态的牛中剩余承重最小的值. #include<iostream> ...

随机推荐

  1. win10虚拟桌面;一不小心按错了突然只剩下桌面,启动的程序都没了

    先说如何关闭虚拟桌面:ctrl+win+F4(万一你还没看到怎么关闭虚拟桌面,就创建并调整到虚拟桌面,会很懵的,因为你启动的所有程序全部都突然消失了,只剩下开机的桌面了): win10有个功能,虚拟桌 ...

  2. CSS 规范 命名规则

    http://nec.netease.com/standard/css-practice.html

  3. Linux下开启计划任务日志

    crontab记录日志 修改rsyslog vim /etc/rsyslog.d/50-default.conf (我的是root用户) 搜索cron 把如下行之前的注释"#"去掉 ...

  4. Unity入门&物理引擎

    一.Unity六大模块 首先,Unity界面有六大模块,分别是:Hierarchy,Scene,Game,Inspector,Project,Console.下面对这六个视图的功能进行详解. 1.Hi ...

  5. LINUX 设置 backspace为删除键

    描述 :在linux/unix平台上的 sqlplus中,如果输错了字符,要想删除,习惯性的按下backspace键后,发现非但没有删除想要删掉的字符,还多出了两个字符^H. 原因:由于终端默认ctr ...

  6. javax.servlet.http.HttpServletResponse.getStatus()I

    感谢作者分享:http://blog.csdn.net/szwangdf/article/details/42145463 -------------------------------------- ...

  7. python 遍历enumerate

    在python中enumerate的用法多用于在for循环中得到计数,本文即以实例形式向大家展现python中enumerate的用法.具体如下: enumerate参数为可遍历的变量,如 字符串,列 ...

  8. Javascript之基本类型和引用类型

    ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值,基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象. 在将一个值赋给变量时,解析器必须确定这个值是基本 ...

  9. lower_bound和upper_bound的实现和基本用法

    最近一直在学dp,但是感觉进度明显慢了很多,希望自己可以加一把劲,不要总是拖延了... 在LIS的优化中我遇到了二分查找的问题,之前也知道lower_bound和upper_bound两个函数,但是没 ...

  10. HDU 6118 度度熊的交易计划(最小费用最大流)

    Problem Description度度熊参与了喵哈哈村的商业大会,但是这次商业大会遇到了一个难题: 喵哈哈村以及周围的村庄可以看做是一共由n个片区,m条公路组成的地区. 由于生产能力的区别,第i个 ...