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

显然设置 f i f_i fi 为状态为 i i i 的情况下最大和谐度。枚举各个子集 i i i 再枚举 i i i 的各个子集 j j j 进行转移,复杂度 O ( 2 2 n ) O(2^{2n}) O(22n) n ≤ 16 n\le16 n16,显然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;
}

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

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

举个例子

i=10101
j=10100
  10001
  10000
  00101
  10000
  00000

那么复杂度是

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

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

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

用二项式定理计算:

= ∑ i = 1 n ( n I ) × 2 i × 1 n − 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 ( n 3 ) 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值