显然设置 fif_ifi 为状态为iii 的情况下最大和谐度。枚举各个子集 iii 再枚举 iii 的各个子集 jjj 进行转移,复杂度O(22n)O(2^{2n})O(22n),n≤16n\le16n≤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;
}
所以考虑只枚举 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|}∑N⊇I∑I⊇J1=∑N⊇I2∣I∣
由于 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×1n−1
=(1+2)n−1=(1+2)^n−1=(1+2)n−1
所以时间复杂度为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;
}