[BZOJ1226][SDOI2009]学校食堂Dining
Posted xjr_01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1226][SDOI2009]学校食堂Dining相关的知识,希望对你有一定的参考价值。
[BZOJ1226][SDOI2009]学校食堂Dining
试题描述
输入
输出
输入示例
2 5 5 2 4 1 12 0 3 3 2 2 2 5 0 4 0
输出示例
16 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。
题解
发现 Bi 非常小,这样一个合法的选择状态一定长成这个样子:我们考虑前 i + 8 个学生,前面 i 个学生都处理完了,只有最后 8 个学生是不确定的。于是我们不难想到把最后 8 个学生的处理状态压成一个二进制。
于是一个初步的状态设计就出来了:f(i, S, j) 表示前 i 个学生都处理完了,最后 8 个学生的处理状态为 S,上一次处理的学生要求的美味度为 j。但是状态数有 1000 * 256 * 1000,转移数有 8,会超时,并且如果不用滚动数组还会 MLE。
那么改一下最后一维状态,上一次处理的学生到最后一个位置(即位置 i + 8)的距离不会超过 15(想一想,为什么),于是我们把 j 换成“上一个学生到 i + 8 的距离”就好了。
暴力 dp:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if(Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } int read() { int x = 0, f = 1; char c = Getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = Getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = Getchar(); } return x * f; } #define maxn 1010 #define maxv 1002 #define maxs 256 #define oo 2147483647 int n, A[maxn+10], Back[maxn+10], f[2][maxs][maxv]; void up(int& a, int b) { a = min(a, b); return ; } int main() { int T = read(); while(T--) { n = read(); for(int i = 1; i <= n; i++) A[i] = read(), Back[i] = read(); int all = (1 << 8) - 1, use[10], cntu; for(int i = 0; i < 2; i++) for(int S = 0; S <= all; S++) for(int j = 0; j < maxv; j++) f[i][S][j] = oo; f[0][0][1001] = 0; bool cur = 0; for(int i = 0; i < n; i++, cur ^= 1) { for(int S = 0; S <= all; S++) for(int j = 0; j < maxv; j++) f[cur^1][S][j] = oo; for(int S = 0; S <= all; S++) { if(S & 1) { for(int j = 0; j < maxv; j++) up(f[cur^1][S>>1][j], f[cur][S][j]); continue; } int mnr = min(n, i + 1 + Back[i+1]); for(int p = 1; p < 8 && i + 1 + p <= n; p++) if(!(S >> p & 1)) up(mnr, i + 1 + p + Back[i+1+p]); cntu = 0; for(int p = 1; p < 8 && i + 1 + p <= n; p++) if(!(S >> p & 1) && i + 1 + p <= mnr) use[++cntu] = i + 1 + p; for(int j = 0; j < maxv; j++) if(f[cur][S][j] < oo) { for(int x = 1; x <= cntu; x++) { int p = use[x]; up(f[cur][S|(1<<p-1-i)][A[p]], f[cur][S][j] + (j == maxv - 1 ? 0 : (j | A[p]) - (j & A[p]))); } up(f[cur^1][S>>1][A[i+1]], f[cur][S][j] + (j == maxv - 1 ? 0 : (j | A[i+1]) - (j & A[i+1]))); } } } int ans = oo; for(int j = 0; j < maxv; j++) up(ans, f[cur][0][j]); printf("%d\n", ans); } return 0; }
AC:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); } return x * f; } #define maxn 1010 #define maxs 256 #define maxd 16 #define oo 2147483647 int n, A[maxn], Back[maxn], f[maxn][maxs][maxd]; void up(int& a, int b) { a = min(a, b); return ; } int main() { int T = read(); while(T--) { n = read(); for(int i = 1; i <= n; i++) A[i] = read(), Back[i] = read(); for(int i = 0; i <= n; i++) for(int S = 0; S < maxs; S++) for(int d = 0; d < maxd; d++) f[i][S][d] = oo; f[0][0][0] = 0; for(int i = 0; i <= n; i++) for(int S = 0; S < maxs; S++) { if(S & 1) { for(int d = 0; d < maxd; d++) if(f[i][S][d] < oo) up(f[i+1][S>>1][d+1], f[i][S][d]); continue; } int use[10], cntu = 0, mnr = n; for(int j = 0; j < 8 && i + j + 1 <= n; j++) if(!(S >> j & 1)) up(mnr, Back[i+j+1] + i + j + 1); for(int j = 0; j < 8 && i + j + 1 <= mnr; j++) if(!(S >> j & 1)) use[++cntu] = i + j + 1; for(int d = 0; d < maxd; d++) if(f[i][S][d] < oo) { int lv = (!i && !S) ? -1 : A[i+8-d]; for(int x = 1; x <= cntu; x++) { int p = use[x]; up(f[i][S|(1<<p-i-1)][i+8-p], f[i][S][d] + (lv < 0 ? 0 : (A[p] | lv) - (A[p] & lv))); } } } int ans = oo; for(int d = 0; d < maxd; d++) up(ans, f[n][0][d]); printf("%d\n", ans); } return 0; }
以上是关于[BZOJ1226][SDOI2009]学校食堂Dining的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1226 [SDOI2009]学校食堂Dining(状压DP)
bzoj1226: [SDOI2009]学校食堂Dining 状压dp