• 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];
        }
    };
  • 相关阅读:
    5000 端口 转发
    程序的运行环境=内存+运行库+系统调用
    日志异步落库
    malloc分配的空间是连续的吗?
    PE/ELF文件里面存的是什么呢?
    [Python]编码声明:是coding:utf-8还是coding=utf-8呢
    基于可执行代码的缓冲区溢出检测模型
    SU Demos-06Selecting Traces
    SU Demos-05Sorting Traces-03susorty
    SU Demos-05Sorting Traces-02Demos
  • 原文地址:https://www.cnblogs.com/rhythmic/p/14097286.html
Copyright © 2020-2023  润新知