UVa12235 Help Bubu

难啊!

分析题目,发现书高范围挺小的,估摸着是个状态压缩。

然后就卡住了,再然后无比熟练的找到了题解

先思考状态吧。首先前 i 个,选 j 个肯定是要有的。

决策肯定是选和不选。

不选的时候,messval的值肯定跟上一个结尾的高度有关,所以状态里肯定有结尾的高度。

很明显,肯定要记录 拿走或者剩余哪些高度 以及 所有的高度。

于是终于思考出状态 :

 int f[2][MAXN][MAXH][10];//前i个, 选j个, 书架上剩余书目集合, 最后一本书的高度 

然后就可以码了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e2 + 5;
const int MAXH = (1 << 8) + 2;

int f[2][MAXN][MAXH][10];//前i个, 选j个, 书架上剩余书目集合, 最后一本书的高度
int N, K;

int main()
{
    int T = 0;
    while(cin>>N>>K, (N + K))
    {
        int d = 0, all = 0;
        memset(f[d], 0x3f, sizeof(f[d]));
        for(int i = 0; i < N; i++){
            int h; scanf("%d", &h);
            h -= 25;
            d ^= 1; memset(f[d], 0x3f, sizeof(f[d]));
            f[d][i][(1 << h)][h] = 1;
            for(int j = 0; j <= min(i, K); j++)
                for(int s = all; s; s = (s - 1) & all)
                    for(int k = 0; k < 8; k++){
                        if(f[d ^ 1][j][s][k] == INF) continue;
                        if(h == k) f[d][j][s][h] = min(f[d][j][s][h], f[d ^ 1][j][s][k]);//不拿
                        else {
                            f[d][j][s | (1 << h)][h] = min(f[d][j][s | (1 << h)][h], f[d ^ 1][j][s][k] + 1);
                            f[d][j + 1][s][k] = min(f[d][j + 1][s][k], f[d ^ 1][j][s][k]);//
                        }
                    }
            all |= (1 << h);
        }
        int ans = INF;
        for(int j = 0; j <= K; j++)
            for(int s = all; s; s = (s - 1) & all)
                for(int k = 0; k < 8; k++){
                    if(f[d][j][s][k] == INF) continue;
                    int cnt = 0;
                    for(int tmp = s ^ all; tmp; tmp >>= 1)
                        if(tmp & 1) ++cnt;
                    ans = min(ans, f[d][j][s][k] + cnt);
                }
        printf("Case %d: %d\n\n", ++T, ans);
    }
    return 0;
}

 

posted @ 2018-07-09 19:39  俺是小程  阅读(177)  评论(0编辑  收藏  举报