题目链接:点击打开链接
思路:
比赛时查一点出, 需要加一个优化才能防止超时(恶心), 状态很容易想到: d[i][j][s][k]表示前i本书拿了j本没拿的书的集合是s没拿的书的最后一本是k的最优解。
为什么状态压缩的是目前桌子上的书的集合呢? 因为我们要防止一种情况:那就是如果对于高度为H的一种书, 我们都拿走了, 那么还要放回桌子上, 最优解要+1, 这样表示之后, 我们只要判断一下有几种书桌子上没有就行了。
细节参见代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include <cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const double eps = 1e-6; const double PI = acos(-1); const int mod = 1000000000 + 7; const int INF = 0x3f3f3f3f; // & 0x7FFFFFFF const int seed = 131; const ll INF64 = ll(1e18); int T,n,K,a[111],d[2][111][(1<<8)][10], kase = 0; int tot, state,one[1<<8]; inline void init(int u) { for(int j = 0; j <= K; j++) { for(int s = 0; s < (1<<(tot+1)); s++) { for(int k = 0; k <= tot+1; k++) { d[u][j][s][k] = INF; } } } } void Initial() { for (int i = 0; i < (1<<8); ++i) { for (int j = 0; j < 8; ++j) if (i & (1<<j)) one[i]++; } } int main() { Initial(); while(~scanf("%d%d", &n, &K)) { if(n == 0 && K == 0) break; tot = 0; state = 0; for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); a[i] -= 25; tot = max(tot, a[i]); state |= 1<<a[i]; } int u = 0; init(u); d[u][0][0][tot+1] = 0; for(int i = 0; i < n; i++) { int id = a[i+1]; u ^= 1; init(u); for(int j = 0; j <= K; j++) { for(int s = 0; s < (1<<(tot+1)); s++) { for(int k = 0; k <= tot+1; k++) { int& ans = d[u^1][j][s][k]; if(ans == INF) continue; if(j < K) d[u][j+1][s][k] = min(d[u][j+1][s][k], ans); if(k != id) d[u][j][s|(1<<id)][id] = min(d[u][j][s|(1<<id)][id], ans+1); else d[u][j][s][id] = min(d[u][j][s][id], ans); } } } } int ans = INF; for(int j = 0; j <= K; j++) { for(int s = 0; s < (1<<(tot+1)); s++) { for(int k = 0; k < tot+1; k++) { int cur = 0; if(d[u][j][s][k] == INF) continue; int st = state ^ s; ans = min(ans, d[u][j][s][k] + one[st]); } } } printf("Case %d: %d\n\n", ++kase, ans); } return 0; }
时间: 2024-11-08 19:23:45