• 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来获得所有情况的最大值。

    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    #include<vector>
    #include<list>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    #include<unordered_map>
    #include<unordered_set>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<stdio.h>
    #include<functional>
    
    using namespace std;
    
    int dp[1005][1030];
    int waste[1005];
    int main(){
    	int N, Q, M;
    	scanf("%d %d %d", &N, &M, &Q);
    	for (int i = 0; i < N; i++){
    		scanf("%d", &waste[i]);
    	}
    	for (int i = 0; i < N; i++){
    		for (int j = 0; j < (1 << min(i + 1, M)); j++){
    			int k = 0;
    			int jj = j;
    			while (jj){
    				k += (jj & 1);
    				jj >>= 1;
    			}
    			if (k > Q)
    				dp[i][j] = 0;
    			else{
    				jj = j >> 1;
    				dp[i][j] = max(dp[i][j], i > 0 ? dp[i - 1][jj] : 0);				
    				jj |= (1 << min(i, M-1));
    				dp[i][j] = max(dp[i][j], i > 0 ? dp[i - 1][jj] : 0);
    				if (j & 1)
    					dp[i][j] += waste[i];
    			}
    		}
    	}
    	int result = 0;
    	for (int x = 0; x < (1 << min(M, N)); x++){
    		result = max(result, dp[N - 1][x]);
    	}
    	printf("%d
    ", result);
    	return 0;
    }
    
  • 相关阅读:
    从头来之【图解针对虚拟机iOS开发环境搭建】 (转)
    换工作?请记得8、18、48与72这四个密码(转)
    php
    linux上svn连接visual svn server时ssl鉴权失败,问题解决(转)
    javamail发送邮件的简单实例(转)
    稀疏矩阵
    Redis11种Web应用场景
    说说ShellExecuteEx
    怎样从host之外连接到docker container
    hadoop日志分析
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/5504006.html
Copyright © 2020-2023  润新知