bzoj1226/luogu2157 学校食堂 (状压dp)
我们先约定:(左) 窗口_人人人人人 (右)
可以发现,我们只需要知道最靠左的还没打饭的人 以及它身后7个人的状态 以及上一个打饭的人是谁
因为他左面的就都打过了 右面7个人以后肯定还没打
可以设f[i][j][k]表示这是第i个人,身后7个人的状态是j,上一个打饭的是k
但其实上一个打饭的离他最远也就是8,所以可以只记i和k的差值,为了避免出负数再加个10之类的
考虑怎么转移,有两种情况
1.i身后的某个人打饭:找到j中是0的一位x,同时保证x左面的没打饭的人+这个人的容忍度<=x,也就是保证这个转移合法
2.i自己打饭:找到i右面第一个是0的位置,转移到这个位置
转移的时候更新一下k就好了
#include<bits/stdc++.h>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
const int maxn=,maxs=,maxb=; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,v[maxn],f[maxn][maxs][maxb],b[maxn],bin[maxb]; int gettime(int i,int j,int k){
return (i+k-)?(v[i+j]|v[i+k-])-(v[i+j]&v[i+k-]):;
} int main(){
//freopen("","r",stdin);
int i,j,k,l;
bin[]=;for(i=;i<=;i++) bin[i]=bin[i-]<<;
for(int T=rd();T;T--){
N=rd();
for(i=;i<=N;i++)
v[i]=rd(),b[i]=rd();
for(i=N+;i<=N+;i++)
b[i]=;
CLR(f,);
f[][][]=;int ans=1e9+;
for(i=;i<=N;i++){
for(j=;j<bin[b[i]+];j++){
for(k=;k<=+b[i];k++){
if(f[i][j][k]>=1e9) continue;
int mi=;
for(l=;l<=b[i]&&l<=mi;l++){
if(!(j&bin[l])) f[i][j|bin[l]][l+]=min(f[i][j|bin[l]][l+],f[i][j][k]+gettime(i,l,k));
if(!(j&bin[l])) mi=min(mi,l+b[i+l]);
}
for(l=;l<=b[i];l++)
if(!(j&bin[l])) break;
f[i+l][j>>l][-l]=min(f[i+l][j>>l][-l],f[i][j][k]+gettime(i,,k));
if(i+l>N) ans=min(ans,f[i+l][j>>l][-l]);
}
}
}
printf("%d\n",ans);
}
return ;
}
bzoj1226/luogu2157 学校食堂 (状压dp)的更多相关文章
- BZOJ 1226 学校食堂(状压DP)
状压DP f(i,j,k)表示前i−1个人已经吃了饭,且在i之后的状态为j的人也吃了饭(用二进制表示后面的状态),最后吃的那个人是i之后的第k个 (注意k可以是负数) 然后 如果j&1=1那么 ...
- P2157 [SDOI2009]学校食堂 状压DP
题意: 排队买饭,时间为前一个人和后一个人的异或和,每个人允许其后面B[i] 个人先买到饭,问最少的总用时. 思路: 用dp[i][j][k] 表示1-i-1已经买好饭了,第i个人后面买饭情况为j,最 ...
- Luogu 2157 [SDOI2009]学校食堂 - 状压dp
Solution 比较好想的dp, 但是坑不少QAQ, 调半天 由于容忍度 $b_i$<= 7, 所以可以考虑将第$i$个人接下来的$b_i$ 个人作为一个维度记录状态. 于是我们定义数组$f[ ...
- SDOI 2009 学校食堂 状压dp
这个题的关键处1 紧跟着他的bi个人 —— 由此得出任意一个状态都可以表示为 有第一个人没吃到饭做分隔的前面所有人已吃饭,并用1<<8表示之后的(包括他)的八个人的状态2 信息仍然是上一个 ...
- [学习笔记]状压dp
状压 \(dp\) 1.[SDOI2009]Bill的挑战 \(f[i][j]\) 表示匹配到字符串的第 \(i\) 位状态为 \(j\) 的方案数 那么方程就很明显了,每次枚举第 \(i\) 位的字 ...
- bzoj 1226 [SDOI2009]学校食堂Dining(状压DP)
Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以 ...
- [luoguP2157] [SDOI2009]学校食堂Dining(状压DP)
传送门 这种鬼畜的状压DP...第一次见 看到 0 <= Bi <= 7 就应该想到状态压缩,然而此题实在太鬼畜,想到也没什么乱用 f[i][j][k]表示前i-1个人全部吃完,i~i+7 ...
- 【BZOJ1226】学校食堂(动态规划,状态压缩)
[BZOJ1226]学校食堂(动态规划,状态压缩) 题面 BZOJ 洛谷 题解 发现\(b\)很小,意味着当前这个人最坏情况下也只有后面的一小部分人在他前面拿到饭. 所以整个结果的大致顺序是不会变化的 ...
- 状压DP之LGTB 与序列
题目 思路 这道题竟然是状压DP,本人以为是数论,看都没看就去打下一题的暴力了,哭 \(A_i\)<=30,所以我们只需要考虑1-58个数,再往后选的话还不如选1更优,注意,1是可以重复选取的, ...
随机推荐
- 【学习总结】Git学习-参考廖雪峰老师教程一-Git简介
学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...
- 提高工作效率-window热键
一.虚拟桌面 Ctrl win D 创建另一个桌面 Ctrl win 左右箭头 来回切换桌面 Ctrl win F4 关闭当前虚拟桌面 二.窗口 win M ...
- 转:VIM选择文本块/复制/粘贴
VIM选择文本块/复制/粘贴 - lcj_cjfykx的专栏 - CSDN博客https://blog.csdn.net/lcj_cjfykx/article/details/9091569
- ubuntu使用squid搭建代理
安装squid //检查是否安装squid which squid // apt update sudo apt install squid 配置squid的配置文件squid.conf //备份sq ...
- 文件操作mode学习总结-----Python学习总结【第四篇】:Python之文件操作(文件、正则、json、pickle)
非常全的博客,防丢链接参考https://www.cnblogs.com/madsnotes/articles/5521551.html 1.文件操作 1.1 操作流程 1)文件打开 2)文件操作 3 ...
- 爱上linux 简单实现移动办公处理环境.
1. 这周一直在鼓捣linux上面的环境测试. 简单的将 我们的产品部署到了linux上面 详情见前面的 blog 2. 有时候下班了 或者是 在WC (科技园wc排队 说多了都是泪) 或者是眼睛不舒 ...
- PHP二维数组(或任意维数组)转换成一维数组的方法汇总(实用)
目录 1 array_reduce函数法 2 array_walk_recursive函数法 3 array_map函数法 假设有下面一个二维数组: $user = array( '0' => ...
- Day 4-4 shutil模块
常用方法: import shutil f = open("conf.ini", "r") f1 = open("shutil.ini", ...
- 对数log
a的x次方等于N(a>0,且a不等于1),那么数x叫做以a为底N的对数(logarithm),记作x=logaN.其中,a叫做对数的底数,N叫做真数.
- ArcGIS 添加 MarkerSymbol 弹出“图形符号无法序列化为 JSON”错误
今天在做一个demo,向自定义图层中添加MarkerSymbol的时候,弹出“图形符号无法序列化为 JSON”错误,之前都没有出现过这个问题,我们首先来看一看我是怎样去添加图层,然后向图层中添加Gra ...