AtCoder Contest199 E - Permutation(状压dp)
发布日期:2021-06-30 10:33:54
浏览次数:2
分类:技术文章
本文共 1062 字,大约阅读时间需要 3 分钟。
题意
求 [ 1 , n ] [1,n] [1,n]的满足一下条件的排列方案数
对于 m m m个限制,满足
a 1 , a 2 . . . a x i a_1,a_2...a_{x_i} a1,a2...axi中至多有 z i z_i zi个数小于等于 y i y_i yi
n < = 18 , m < = 100 n<=18,m<=100 n<=18,m<=100
比较裸的状压 D P \rm DP DP吧
定义 f [ i ] f[i] f[i]表示填数状态为 i i i时的合法方案数,第 j j j位二进制为 1 1 1表示数字 j j j已经被填过
比如 i i i中有 x x x个 1 1 1,说明已经填充了 k k k个数
那么每次 O ( n ) O(n) O(n)枚举第 k + 1 k+1 k+1个位置填哪个数,并检查是否满足 x i = k + 1 x_i=k+1 xi=k+1的那些限制
这样每次转移,都考虑了可能的限制
总体复杂度为 O ( 2 n ∗ n ) O(2^n*n) O(2n∗n),略带常数(因为有时候需要考虑 m m m个限制)
#includeusing namespace std;long long f[1<<18];int n,m,pre[22];typedef pair p;vector vec[22];int main(){
cin >> n >> m; for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); vec[x].push_back( p(y,z) ); } f[0] = 1; for(int i=0;i<(1<>(j-1))&1 ); for(int j=1;j<=n;j++) pre[j] += pre[j-1]; for(int j=1;j<=n;j++) { if( (i>>(j-1))&1 ) continue; //在这个位置放置j int flag = 1; for(auto v:vec[pre[n]+1] ) if( pre[v.first]+( j<=v.first )>v.second ) flag = 0; if( flag ) f[i|(1<<(j-1))] += f[i]; } } cout << f[(1<
转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/117534549 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月12日 08时47分21秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
leetcode 1143. 最长公共子序列
2019-04-30
leetcode 83. 删除排序链表中的重复元素
2019-04-30
智能体 Intelligent Agent
2019-04-30
Network Compression网络压缩(一)
2019-04-30
GAN系列(零)—— GAN的发展(两条路线)
2019-04-30
Conditional GAN (CGAN) 条件生成网络
2019-04-30
强化学习(三) —— Policy Gradient 策略梯度
2019-04-30
docker安装oracle(win10)
2019-04-30
Cloudera Quickstart & HUE
2019-04-30
HUE
2019-04-30
CDH
2019-04-30
行为树 BT
2019-04-30
Cassandra & CQL
2019-04-30
Oracle数据库
2019-04-30
Oracle数据库命令
2019-04-30
plsql
2019-04-30
有限状态机FSM
2019-04-30
Win10 Docker
2019-04-30
Python绘制动画并保存为gif/mp4 (matplotlib)
2019-04-30
PRM概率路线图
2019-04-30