显然设置 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 n≤16,显然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|} ∑N⊇I∑I⊇J1=∑N⊇I2∣I∣
由于 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×1n−1
= ( 1 + 2 ) n − 1 =(1+2)^n−1 =(1+2)n−1
所以时间复杂度为 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;
}