题目链接:交换茸角
如果可行。那么对于n个鹿,最多n-1次交换即可。
否则,我们一定可以从中选出不相交的子集替换答案。然后枚举子集dp即可。
判断是否可行,即sort之后两两是否合法。
int i=(s-1)&s;i;i=(i-1)&s 这样即可枚举到s的所有子集,复杂度为 3 ^ n
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=17,inf=0x3f3f3f3f;
int n,c,a[N],b[N],dp[1<<N];
inline int calc(int s){
int res=0; vector<int> v;
for(int i=0;i<n;i++) if(s>>i&1) v.push_back(a[i]),v.push_back(b[i]),res++;
sort(v.begin(),v.end());
for(int i=1;i<v.size();i+=2) if(v[i]-v[i-1]>c) return inf;
return res-1;
}
signed main(){
cin>>n>>c;
for(int i=0;i<n;i++) cin>>a[i]>>b[i];
for(int i=1;i<(1<<n);i++) dp[i]=calc(i);
for(int s=1;s<(1<<n);s++){
for(int i=(s-1)&s;i;i=(i-1)&s){
dp[s]=min(dp[s],dp[i]+dp[i^s]);
}
}
if(dp[(1<<n)-1]>=inf) puts("-1");
else cout<<dp[(1<<n)-1];
return 0;
}