暴力求解,换个问法,找k个数字,这k个数字的异或和等于(1<<n) - 1,数字的第i位为1,代表选择第i个物品,求最小不兼容性
考虑状压dp,很玄学,这么暴力居然真的可行,以后要莽一点,状压直接上就好了。。。。。其实挺简单
#include<iostream> #include<cstring> #include<queue> #include<algorithm> using namespace std; typedef long long ll; class Solution { public: vector<pair<int,int> >ins; ll dp[100000]; int minimumIncompatibility(vector<int>& nums, int k) { int len = nums.size(); if(k == len) return 0; int n = 1<<len;//n个状态 vector<int>a; ins.clear(); int vis[200]; for(int i=1;i<n;i++){ dp[i] = 1e9; int t = i; a.clear(); int c = 0; while(t){ if(t&1){ a.push_back(nums[c]); } t /= 2; c++; } if(a.size() != len/k) continue; for(int j=0;j<a.size();j++){ vis[a[j]] = 0; } int f = 0; int mx = -111; int mi = 1e9; for(int j=0;j<a.size();j++){ if(vis[a[j]]){ f = 1; break; } vis[a[j]] = 1; mi = min(mi,a[j]); mx = max(mx,a[j]); } if(f) continue; ins.push_back(make_pair(i,mx - mi));//这个状态的价值 } dp[0] = 0; for(int i=0;i<n;i++){ if(dp[i] == 1e9) continue; for(int j=0;j<ins.size();j++){ int x = ins[j].first; int y = ins[j].second; if((i&x) != 0) continue;//有交点 dp[i+x] = min(dp[i+x],dp[i] + y); } } if(dp[n - 1] > 100000) return -1; return dp[n-1]; } };