题目:Mixed Up Cows
思路:
状态压缩DP。
f[i][j]:i的二进制表示已经排过的牛,j表示最新的被加进来的牛。对于选择接下要加进来的牛u,只需要考虑他和j的关系(只和相邻的有关),及只要u和j的距离<=k,就可以将u加入i中。此时,i就被扩充为 i|(1<<u) 。考虑多个u后,可得状态转移方程 f[i|(1<<u)][u]+=f[i][j] (u不属于i) 。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;int n,k;
int a[20]= {0};
long long f[70000][20]= {0};int main() {scanf("%d%d",&n,&k);for(int i=0; i<n; i++) {int x;scanf("%d",&x);a[i]=x;}for(int i=0;i<n;i++){f[1<<i][i]=1;}int m=(1<<n)-1;for(int i=0; i<=m; i++) { //状态 for(int j=0; j<n; j++) {if(!(i&(1<<j))) continue;for(int u=0;u<n;u++){if(i&(1<<u)||abs(a[u]-a[j])<=k) continue; //u已经在i中或距离小于kf[i|(1<<u)][u]+=f[i][j];}}}long long ans=0;for(int i=0;i<n;i++){ans+=f[m][i];}printf("%lld",ans);return 0;
}