YbtOJ 状压dp E. 1.最优组队

本文介绍了一种针对状态转移方程的优化方法,通过仅枚举子集而非所有可能集合来降低算法的时间复杂度。从初始的O(2^2n)优化到了O(n^3),适用于解决涉及子集和状态转移的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

显然设置 fif_ifi 为状态为iii 的情况下最大和谐度。枚举各个子集 iii 再枚举 iii 的各个子集 jjj 进行转移,复杂度O(22n)O(2^{2n})O(22n)n≤16n\le16n16,显然TLE。
#include<bits/stdc++.h>//注意位运算的优先级,加括号控制
using namespace std;
const int maxn=1e5+10;
int f[maxn],n,top;
signed main()
{
    cin>>n;
    top=(1<<n)-1;
    for(int i=1;i<=top;i++) cin>>f[i];
    for(int i=1;i<=top;i++)
        for(int j=1;j<=top;j++)
            if(i!=j&&((i|j)==i)) f[i]=max(f[i],f[j]+f[i^j]);
    cout<<f[top]<<endl;
    return 0;
}

所以考虑只枚举 iii 的子集进行优化,

for(int j=(i-1)&i;j;j=(j-1)&i)

举个例子

i=10101
j=10100
  10001
  10000
  00101
  10000
  00000

那么复杂度是

∑N⊇I∑I⊇J1=∑N⊇I2∣I∣\sum_{N\supseteq I }^{} \sum_{I\supseteq J}^{}1=\sum_{N\supseteq I }^{}2^{|I|}NIIJ1=NI2I

由于 NNN 中大小为iii的子集个数是(nI)\begin{pmatrix}n\\I\end{pmatrix}(nI),所以:

=∑i=1n(nI)×2i=\sum_{i=1}^{n}\begin{pmatrix}n\\I\end{pmatrix}\times 2^i=i=1n(nI)×2i

用二项式定理计算:

=∑i=1n(nI)×2i×1n−1=\sum_{i=1}^{n}\begin{pmatrix}n\\I\end{pmatrix}\times 2^i\times1^{n-1}=i=1n(nI)×2i×1n1

=(1+2)n−1=(1+2)^n−1=(1+2)n1

所以时间复杂度为O(n3)O(n^3)O(n3)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int f[maxn],n,top;
signed main()
{
    cin>>n;
    top=(1<<n)-1;
    for(int i=1;i<=(1<<n)-1;i++) cin>>f[i];
    for(int i=1;i<=top;i++)
        for(int j=(i-1)&i;j;j=(j-1)&i)
            if(i!=j&&((i|j)==i)) f[i]=max(f[i],f[j]+f[i^j]);
    cout<<f[top]<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值