一看n那么小,那一定是状压dp了(表示从没写过,慌)。
首先dp[i][j](i 是一个二进制数,第x位为1代表选了第x头牛),表示 i 这个状态最后一头牛是第 j 头牛时的方案数。
然后当 j 被选上时,即 if(i & (1 << (j - 1)))时,我们在枚举倒数第二头牛p,也是当他存在时,且满足 abs(s[p] - s[j]) > k时,dp[i][j] += dp[i ^ (1 << (j - 1))][p],因为最后一头牛为p时,j 还没有被选,所以 j 这一位要亦或掉。
初始化就是只选一头牛的选法时一种,dp[1 << (i - 1)][i] = 1.
令 ms = (1 << n) - 1,则答案ans = sum(dp[ms][i]) (i = 1~n).
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<stack> 8 #include<queue> 9 #include<vector> 10 #include<cctype> 11 using namespace std; 12 #define space putchar(' ') 13 #define enter puts("") 14 #define Mem(a) memset(a, 0, sizeof(a)) 15 typedef long long ll; 16 typedef double db; 17 const int INF = 0x3f3f3f3f; 18 const db eps = 1e-8; 19 const int maxn = 20; 20 const int Maxs = 7e4; 21 inline ll read() 22 { 23 ll ans = 0; 24 char ch = getchar(), last = ' '; 25 while(!isdigit(ch)) {last = ch; ch = getchar();} 26 while(isdigit(ch)) {ans = (ans << 3) + (ans << 1) + ch - '0'; ch = getchar();} 27 if(last == '-') ans = -ans; 28 return ans; 29 } 30 inline void write(ll x) 31 { 32 if(x < 0) putchar('-'), x = -x; 33 if(x >= 10) write(x / 10); 34 putchar(x % 10 + '0'); 35 } 36 37 int n, k, a[maxn]; 38 ll dp[Maxs][maxn]; 39 40 int main() 41 { 42 n = read(); k = read(); 43 for(int i = 1; i <= n; ++i) a[i] = read(), dp[1 << (i - 1)][i] = 1; 44 int ms = (1 << n) - 1; 45 for(int i = 1; i <= ms; ++i) 46 for(int j = 1; j <= n; ++j) 47 if(i & (1 << (j - 1))) 48 for(int p = 1; p <= n; ++p) 49 if(p != j && (i & (1 << (p - 1))) && abs(a[p] - a[j]) > k) 50 dp[i][j] += dp[i ^ (1 << (j - 1))][p]; 51 ll ans = 0; 52 for(int i = 1; i <= n; ++i) ans += dp[ms][i]; 53 write(ans); enter; 54 return 0; 55 }