Gym 100917EExtreme Permutations(状压dp)

来源:互联网 发布:禁止系统安装软件 编辑:程序博客网 时间:2024/05/17 03:04

参考别人的题解:点击打开链接

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;#pragma comment(linker,"/STACK:102400000,102400000")#define eps 1e-10#define inf 0x3f3f3f3f#define LL long long#define pii pair<int, int>#define MP make_pair#define md (ll + rr >> 1)#define ls i << 1#define rs ls | 1#define lson ll, md, ls#define rson md + 1, rr, rs#define N 30#define M 400020int p[N], id[N], f[1<<15];LL dp[1<<15];int main(){int n, m;scanf("%d", &n);for(int i = 1; i <= n; ++i){scanf("%d", &p[i]);id[p[i]] = i;}m = (n + 1) >> 1;for(int i = 0; i < (1<<m); ++i)for(int j = 0; j < m; ++j)if(i & (1 << j))f[i]++;dp[0] = 1;for(int s = 0; s < (1<<m); ++s){int now = n - f[s];for(int i = 0; i < m; ++i){if((id[now] && id[now] != (i<<1|1)) || (p[i<<1|1] && p[i<<1|1] != now) || (s & (1 << i))) continue;int nxt = s | (1 << i);LL add = dp[s];if(now & 1)dp[nxt] += dp[s];else{int x = now >> 1;int y = id[x] >> 1;if(id[x]){if((id[x] & 1) || ((nxt & (1 << (y-1))) == 0 || (nxt & (1 << y)) == 0)) continue;dp[nxt] += dp[s];}else{int cnt = 0;for(int j = 1; j < m; ++j)if((nxt & (1 << (j - 1))) && (nxt & (1 << j)) && !p[j<<1])cnt++;for(int j = x + 1; j < m; ++j)if(!id[j]) cnt--;dp[nxt] += dp[s] * cnt;}}}}LL ans = dp[(1<<m)-1], q = 1;for(int i = (m - 1) >> 1; i; --i)if(!id[i])ans *= q++;printf("%lld\n", ans);return 0;}


0 0
原创粉丝点击