HDU 3237 Help Bubu(DP)

来源:互联网 发布:c语言逻辑取反 编辑:程序博客网 时间:2024/06/07 00:28

题目链接:点击打开链接

思路:

比赛时查一点出, 需要加一个优化才能防止超时(恶心), 状态很容易想到: 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;// & 0x7FFFFFFFconst 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;}


0 0
原创粉丝点击