zoukankan      html  css  js  c++  java
  • leetcode1681

    /*状态压缩 这种集合元素不是特别多(n<16)的集合等分,可以考虑使用基于二进制的集合状态记录
    首先预处理所有含有n/k元素的value值 用于最优化(动态规划)的时候使用
    然后dp过程其实就是暴搜 针对子集合状态mask 考察他所有的子集合sub 有如下状态转移方程
    dp[mask] = min{sub合法 |dp[mask ^ sub] + value[sub]}*/
    class Solution {
    public:
        int minimumIncompatibility(vector<int>& nums, int k) {
              int n = nums.size();
              vector <int> value(1 << n , -1);
              vector <int> hash(n + 1);
    
              for(int sub = 0;sub < (1 << n);sub++){
                  if(__builtin_popcount(sub) == n / k){//含有n/k元素的子集合的状态
                       for(int j = 0;j < n;j++){//该状态是否合法 [查重]
                            if(sub & (1 << j)){
                                 hash[nums[j]]++;
                            }
                       }
                       int flag = 1;
                       for(int j = 1;j < n + 1;j++){
                            if(hash[j] > 1) {
                                flag = 0;
                                break;
                            }
                       }
                       if(flag == 1){
                            int Min = INT_MAX;
                            int Max = INT_MIN;
                            for(int i = 1;i <= n;i++)
                             if(hash[i] > 0){
                                  Min = min(Min , i);
                                  Max = max(Max , i);
                             }
                             value[sub] = Max - Min;
                       }
                       
    
                        for(int j = 0;j < n;j++){//该状态是否合法 [查重]
                            if(sub & (1 << j)){
                                 hash[nums[j]]--;
                            }
                       }
                  }
              }
    
              vector<int> dp(1 << n , -1);
              dp[0] = 0;
              for(int mask = 0;mask < (1<<n);mask++){
                   if(__builtin_popcount(mask) %(n/k) == 0){
                         for(int sub = mask;sub;sub = (sub - 1)&mask){//枚举当前状态的子集合
                             if(value[sub] != -1 && dp[mask ^ sub] != -1){
                                 //子集合合法(含有规定元素 即提前预处理过)  剩余集合非空(合法)
                                  if(dp[mask] == -1){
                                      dp[mask] = dp[mask ^ sub] + value[sub];
                                  }
                                  else{
                                       dp[mask] = min(dp[mask] , dp[mask^sub] + value[sub]);
                                  }
                             }
                         }
                   }
              }
              return dp[(1 << n) - 1];
        }
    };
  • 相关阅读:
    git如何将一个远程仓库的某个分支拉取到当前分支?
    linux下如何检查内核补丁是否符合社区代码规范?
    javascript快速入门20--Cookie
    javascript快速入门19--定位
    javascript快速入门18--样式
    javascript快速入门17--事件
    javascript快速入门16--表格
    javascript快速入门15--表单
    javascript快速入门15--节点
    javascript快速入门14--DOM基础
  • 原文地址:https://www.cnblogs.com/rhythmic/p/14097286.html
Copyright © 2011-2022 走看看