1 2 3 4

Leetcode 1681. 最小不兼容性

题目链接

 

 暴力求解,换个问法,找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];
    }
};

  

posted @ 2020-12-07 14:31  Lesning  阅读(236)  评论(0编辑  收藏  举报