• P1777 帮助 [状压dp]


    帮助

    题目描述见链接 .


    color{red}{正解部分}

    提出的书可以放在任意位置, 所以可以先放在一边, 到最后处理,

    F[i,j,k,s]F[i, j, k, s] 表示处理到第 ii 本书, 提出了 jj 本书, 书架上最后一本书 高度kk, 书架上的书高度状态为 ss 时的 混乱值,
    则决策有两个,

    • ii 提出, F[i,j,k,s]=min(F[i1,j1,k,s])F[i, j, k, s] = min(F[i-1, j-1, k, s])
    • 不将 ii 提出, F[i,j,k,s]=min(F[i1,j,p,s(1<<hi1)]+[pk],F[i1,j,p,s]+[pk])F[i, j, k, s] = min(F[i-1, j, p, s igoplus (1<<h_i-1)] + [p ot= k], color{red}F[i-1, j, p, s] + [p ot= k]) .

    再考虑统计答案, Answer=min(F[N,0K,k,s]+cnt[sU])Answer = min(F[N, 0 ightarrow K, k, s] + cnt[s igoplus U]) .

    其中 cnt[x]cnt[x] 表示 xx 二进制中 11 的个数 .

    按以上方式更新状态时间复杂度 O(N2K228)O(N^2K^22^8), 但若使用状态去更新状态, 时间复杂度 O(N2K28)O(N^2K2^8) .


    color{red}{实现部分}

    • 注意 ss 要开 256256 .
    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 105;
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    int N;
    int K;
    int num;
    int Test_cnt;
    int h[maxn];
    int Mp[maxn];
    int cnt[260];
    int F[maxn][maxn][10][260];
    
    int main(){
            for(reg int i = 1; i < 260; i ++) cnt[i] = cnt[i ^ (i & -i)] + 1;
            while((N = read()) && (K = read())){ 
                    memset(Mp, 0, sizeof Mp); num = 0;
                    for(reg int i = 1; i <= N; i ++){ 
                            h[i] = read()-24;
                            if(!Mp[h[i]]) Mp[h[i]] = ++ num;
                            h[i] = Mp[h[i]];
                    }
                    for(reg int i = 0; i <= N; i ++)
                            for(reg int j = 0; j <= K; j ++)
                                    for(reg int k = 0; k <= num; k ++)
                                            for(reg int s = 0; s < (1<<num); s ++) F[i][j][k][s] = 0x3f3f3f3f;
                    F[0][0][0][0] = 0;
                    for(reg int i = 1; i <= N; i ++)
                            for(reg int j = 0; j <= K; j ++)
                                    for(reg int k = 0; k <= num; k ++)
                                            for(reg int s = 0; s < (1<<num); s ++){
                                                    if(j >= 1) F[i][j][k][s] = std::min(F[i][j][k][s], F[i-1][j-1][k][s]);
                                                    if((s & (1<<h[i]-1)) && k == h[i]){
                                                            int &t = F[i][j][k][s];
                                                            for(reg int p = 0; p <= num; p ++){
                                                                    t = std::min(t, F[i-1][j][p][s] + (p != k));
                                                                    t = std::min(t, F[i-1][j][p][s ^ (1<<k-1)] + (p != k));
                                                            }
                                                    }
                                            }
                    int Ans = N, U = (1<<num)-1;
                    for(reg int j = 0; j <= K; j ++)
                            for(reg int i = 0; i <= num; i ++)
                                    for(reg int s = 0; s < (1<<num); s ++) Ans = std::min(Ans, F[N][j][i][s] + cnt[s ^ U]);
                    printf("Case %d: %d
    
    ", ++ Test_cnt, Ans);
            }
            return 0;
    }
    
  • 相关阅读:
    vmware12中安装MAC OS X 10.10
    AOL search
    [python]错误检测及异常处理try-except
    [推荐]
    [python]打开文件操作open用法
    MAC使用小技巧
    [推荐]
    [python]python中的if, while, for
    [python]python字典
    [python]python列表、元组
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822447.html
Copyright © 2020-2023  润新知