hiho_1044 状态压缩

Posted 农民伯伯-Coding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hiho_1044 状态压缩相关的知识,希望对你有一定的参考价值。

题目大意

    给定N个位置,每个位置i都有一个value[i]值,从中选择若干个位置,使得连续的M个位置中的被选中的位置数目不超过Q,求出所有选择方案中value和最大的方案,输出其最大value和。

分析

    1、可以采用枚举的方式,枚举出所有的选择可能情况,每次枚举成功后,更新全局变量最大值即可。时间复杂度O(2^N).当然会超时...

//index为dfs搜索到的位置,num_in_last_M 为前M个位置中有多少个已经被选中,  
//total_value为搜索到当前位置时,总的value
void dfs(int index, int num_in_last_M, int total_value){
    if (index == N){ //递归出口
        max_value = max_value > total_value ? max_value : total_value;
        return;
    }
    //当前index处的位置不选中
    dfs(index + 1, num_in_last_M, total_value);
    if (index < M){
        if (num_in_last_M < Q){
            used[index] = true; //used[i] 用于表示位置i是否被选中
            dfs(index + 1, num_in_last_M + 1, total_value + wastes[index]);
        }
    }
    else if(num_in_last_M - used[index - M] < Q){
        used[index] = true;
        dfs(index + 1, num_in_last_M - used[index - M] + 1, total_value + wastes[index]);
    }
    //回溯!!!
    used[index] = false;
}

    2、采用动态规划的方式 
    dp[i][j] 表示前i个位置中,位置(i-M+1, i-M+2, ... i)构成的选中情况的二进制表示(0表示未选中,1表示选中)为j时,可以得到的最大值。 
    问题满足最优化子结构:从dp[i-1][k] 过渡到dp[i][j]时,如果dp[i][j]取得了最大值,那么dp[i-1][k]也一定为状态(i-1, k)的最大值; 问题无后效性:从dp[i-1][k]推演到dp[i][j]时,不关心 状态(i-1,k)是如何得到的,只关心最后的结果。 
    在求完dp数组之后,如果想要获得最后的结果,需要遍历dp[N]K来获得所有情况的最大值。

int minValue(int a, int b){
    return a < b ? a : b;
}

int main(){
    scanf("%d %d %d", &N, &M, &Q);
    for (int i = 0; i < N; i++){
        scanf("%d", &wastes[i]);
    }
    memset(used, false, sizeof(used));
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= N; i++){
        //枚举状态(i-1,j)的所有情况j(共1 << minValue(M, i-1)个)
        for (int j = 0; j < (1 << minValue(M, i-1)); j++){
            int total = 0;
            //计算前M-1个位置中有多少个1
            int k = j &((1 << minValue(M-1, i - 1)) -1);
            while (k){
                total += (k & 1);
                k >>= 1;
            }
            //从状态(i-1, j)推演到(i, k) 
            k = ((j << 1) & (1 << minValue(M, i)) - 1);
            //位置i处不选中
            dp[i][k] = dp[i][k] > dp[i - 1][j]? dp[i][k]: dp[i-1][j];
            if (total < Q){
                //位置i处选中
                k |= 1;
                dp[i][k] = dp[i][k] > dp[i - 1][j] + wastes[i - 1]? dp[i][k]: dp[i-1][j] + wastes[i-1];
            }
        }
    }
    max_value = 0;
    //遍历求最大值
    for (int i = 0; i < (1 << minValue(M, N)); i++){
        max_value = max_value > dp[N][i] ? max_value : dp[N][i];
    }
    printf("%d\n", max_value);
    return 0;
}

 

以上是关于hiho_1044 状态压缩的主要内容,如果未能解决你的问题,请参考以下文章

hiho_1048_状态压缩2

hiho_100_八数码

hiho_1050_树中的最长路

动态规划_计数类dp_数位统计dp_状态压缩dp_树形dp_记忆化搜索

hiho_1055_刷油漆

hiho_99_骑士问题