SDOI2009 學校食堂

2022-03-25 18:51:03 字數 1578 閱讀 6614

這道題的思想是$dp$。

首先通過簡單推理發現:$(a|b)-(a\&b)=a\hat{} b$。[$(a\ and\ b) - (a\ or\ b) = a\ xor\ b$]

發現對於第$i$個同學的飯菜的選擇受到2方面影響:

是否在前面的某個沒有選擇的同學$>b_i$的位置;

上一次選擇的同學。

觀察資料資訊可知$b_i \leq 7$。

也就是說如果選擇了第$i$個,那麼最多只能選到第$i+7$個同學。前提是第$i$位同學之前全部選完了。

所以我們用狀壓寫。同時記錄上一輪選的同學相對於第$i$位同學的位置,推算得範圍一定在$-8\sim 7$之間(包含兩邊)。

設$f[i][s][x]$為第$i$個之前的同學全部選完,$s$為第$i$到$i+7$同學是否選擇的狀態,$x$同上,

當第$i$位同學已選擇,就可以轉移到$f[i+1][s>>1][x-1]$;

其他任意情況時,當第$i+bit$位同學可以被選擇時(指不超過未選擇的$b[i]$到$b[i+bit-1]$的範圍),可以轉移到$f[i][s | (1 << bit)][bit]$,貢獻為$t[i+x]\hat{} t[i+bit]$,再取最小值即可。

邊界:$f[1][0][-1] = 0$,其餘為$inf$。

注意$x>0$和第一輪的異或結果為$0$,特判一下即可。

因為c++下標不能為負,注意下標偏移。

1 #include 2

3using

namespace

std;45

#define re register

6#define rep(i, a, b) for (re int i = a; i <= b; ++i)

7#define repd(i, a, b) for (re int i = a; i >= b; --i)

8#define maxx(a, b) a = max(a, b);

9#define minn(a, b) a = min(a, b);

10#define ll long long

11#define inf (1 << 30)

1213 inline int

read()

1920

const

int maxn = 1e3 + 10;21

22int

c, n, t[maxn], b[maxn];

2324

int f[maxn][1

<< 8][16

];25

26int

main() 44}

45 rep(x, 0, 15)46

if (s & 1) minn(f[i+1][s >> 1][x-1

], f[i][s][x]);47}

48}49int ans =inf;

50 rep(i, 0, 8) minn(ans, f[n][1

][i]);

51 printf("

%d\n

", ans);52}

53return0;

54 }

SDOI2009 學校食堂

time limits 1000 ms memory limits 262144 kb detailed limits description 小f 的學校在城市的乙個偏僻角落,所有學生都只好在學校吃飯。學校有乙個食堂,雖然簡陋,但食堂大廚總能做出讓同學們滿意的菜餚。當然,不同的人口味也不一定相同,...

SDOI2009 學校食堂

小f 的學校在城市的乙個偏僻角落,所有學生都只好在學校吃飯。學校有乙個食堂,雖然簡陋,但食堂大廚總能做出讓同學們滿意的菜餚。當然,不同的人口味也不一定相同,但每個人的口味都可以用乙個非負整數表示。由於人手不夠,食堂每次只能為乙個人做菜。做每道菜所需的時間是和前一道菜有關的,若前一道菜的對應的口味是a...

SDOI2009 學校食堂

小f 的學校在城市的乙個偏僻角落,所有學生都只好在學校吃飯。學校有乙個食堂,雖然簡陋,但食堂大廚總能做出讓同學們滿意的菜餚。當然,不同的人口味也不一定相同,但每個人的口味都可以用乙個非負整數表示。由於人手不夠,食堂每次只能為乙個人做菜。做每道菜所需的時間是和前一道菜有關的,若前一道菜的對應的口味是a...