博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[jzoj 5230] 队伍统计(状压DP)
阅读量:6264 次
发布时间:2019-06-22

本文共 1222 字,大约阅读时间需要 4 分钟。

Description

现在有n个人要排成一列,编号为1->n 。但由于一些不明原因的关系,人与人之间可能存在一些矛盾关系,具体有m条矛盾关系(u,v),表示编号为u的人想要排在编号为v的人前面。要使得队伍和谐,最多不能违背k条矛盾关系(即不能有超过k条矛盾关系(u,v),满足最后v排在了u前面)。问有多少合法的排列。答案对10^9+7取模。

n,k<=20,m<=n*(n-1),保证矛盾关系不重复。

Solution

状压DP,f[S][K]表示当前队伍状态为S,违背K条矛盾关系的方案数。

易得转移方程f[S|2^(i-1)][k+sum(i&p[i])]=f[S|2^(i-1)][k+sum(i&p[i])]+F[S][K]
其中i表示某个不在队伍的人,num(i)表示i在二进制下1的个数,p[i]表示排在i后面的人的情况

Code

#include 
#define MOD 1000000007int n, m, k, f[1 << 21][21], p[21], tot[1 << 21];int main(){scanf("%d%d%d", &n, &m, &k);for (int i = 0; i <= (1 << n) - 1; ++i){ int x = i; while (x) { tot[i]++; x &= (x - 1); }}while (m--){ int u, v; scanf("%d%d", &u, &v); p[u] |= (1 << (v - 1));}f[0][0] = 1;for (int i = 0; i <= (1 << n) - 1; ++i) for (int j = 0; j <= k; ++j) if (f[i][j]) for (int g = 1; g <= n; ++g) if (!(i & (1 << (g - 1)))) if (j + tot[i & p[g]] <= k) f[i | (1 << (g - 1))][j + tot[i & p[g]]] = (f[i | (1 << (g - 1))][j + tot[i & p[g]]] + f[i][j]) % MOD;int Ans = 0;for (int i = 0; i <= k; ++i) Ans = (Ans + f[(1 << n) - 1][i]) % MOD;printf("%d\n", Ans);return 0;}

转载于:https://www.cnblogs.com/void-f/p/7581568.html

你可能感兴趣的文章
【修改缓存路径】修改Gradle缓存路径的几种方式
查看>>
Java中Lambda表达式的使用
查看>>
Spring Cloud Sleuth超详细实战
查看>>
如何让windows服务器IIS支持.apk/.ipa文件下载
查看>>
Django import / export实现数据库导入导出
查看>>
php内核分析(八)-zend_compile
查看>>
【转】【高斯】高斯模糊算法[2]
查看>>
教程-Close、Halt、terminate、ExitProcess的区别
查看>>
IOC和DI
查看>>
Entity Framework 4 & 4.1
查看>>
统计在线人数
查看>>
HDU 2282 Chocolate
查看>>
jquery ui datepicker 只能选今天以后的日期
查看>>
控件:Gallery --- 3.(实现图片切换)
查看>>
Struts标签---logic:Iterate使用方法
查看>>
HDOJ-1102 Constructing Roads
查看>>
两分钟彻底让你明白Android Activity生命周期(图文)!
查看>>
关于KMP算法
查看>>
当C++遇到iOS应用开发---SQLITE篇
查看>>
Lucene
查看>>