洛谷 P2157 [SDOI2009]學校食堂
阿新 • • 發佈:2018-08-15
cstring else cpp sizeof ++i scanf int turn return
題意簡述
每個人有一個口味,食堂每次只能為一個人做菜
做每道菜所需的時間是和前一道菜有關的,若前一道菜的對應的口味是a,這一道為b,則做這道菜所需的時間為a 異或 b
每個人都有一個容忍度,最多允許緊跟他身後的Bi 個人先拿到飯菜,
求食堂完成所有菜所需的最少時間
題解思路
使用狀態壓縮。f[i][j][k]表示當前處理第i個人,上一個吃過的人是k,j為第i個人後面7個人的吃飯狀態
如果j & 1 == 1,dp[i + 1][j >> 1][k + 7] = minn(dp[i + 1][j >> 1][k + 7], dp[i][j][k + 8]
否則選出i及後面7個人中的一個吃飯,判斷一下容忍度
代碼
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; int C, n, r, ans; int t[1010], b[1010]; int dp[1010][260][20]; int minn(int &x, int y) {x = min(x, y); } int calc(int i, int k, int l) {return i + k ? t[i + k] ^ t[i + l] : 0; } int main() { scanf("%d", &C); while (C--) { ans = INF; memset(dp, INF, sizeof(dp)); scanf("%d", &n); dp[1][0][7] = 0; for (register int i = 1; i <= n; ++i) scanf("%d%d", &t[i], &b[i]); for (register int i = 1; i <= n; ++i) for (register int j = 0; j < 256; ++j) for (register int k = -8; k <= 7; ++k) if (dp[i][j][k + 8] != INF) if (j & 1) minn(dp[i + 1][j >> 1][k + 7], dp[i][j][k + 8]); else for (register int l = 0, r = INF; l <= 7; ++l) if (!((j >> l) & 1) && i + l <= r) { minn(r, i + l + b[i + l]); minn(dp[i][1 << l | j][l + 8], dp[i][j][k + 8] + calc(i, k, l)); } for (register int i = 0; i <= 8; ++i) minn(ans, dp[n + 1][0][i]); printf("%d\n", ans); } }
洛谷 P2157 [SDOI2009]學校食堂