https://blog.csdn.net/zqy1018/article/details/108791516參考了這篇部落格
思路都在程式碼裡了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(int n){cnt=1;for(int i=0;i<=n;i++)head[i]=0;}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[87],b[87];
/*
設1的個數為c,第i段0的個數為xi
ans = n*(n-1)/2 - c*(c-1)/2 - c*(n-c)/2 - \sum {xi * (xi-1)/2 }
所有對數 (1,1)的對數 (1,0)的對數 (0,0)且直接沒有1的對數
*/
ll dp[83][83][83*83];
//安排好前i個1,最後一個1被安排到j處,花了k步 ,最後一項的結果最小是多少。
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
int c = 0,sz=0;
for(int i=1;i<=n;i++){
cin>>a[i],c+=a[i];
if(a[i])b[++sz]=i;
}
ll ans=n*(n-1)/2-c*(c-1)/2-c*(n-c);
memset(dp,0x3f,sizeof(dp));
ll tp=0;
for(int i=0;i<=sz;i++){
if(i)tp+=max(0,(b[i]-b[i-1]-1)*(b[i]-b[i-1]-2)/2);
dp[i][b[i]][0]=tp;
}
for(int i=1;i<=sz;i++)
for(int k=1;k<=n;k++)
for(int j=0;j<k;j++)
for(int l=0;l<=n*(n-1)/2;l++)
dp[i][k][abs(k-b[i])+l]=min(dp[i][k][abs(k-b[i])+l],dp[i-1][j][l]+max(0,(k-j-1)*(k-j-2)/2));
ll mn=2e18;
for(int i=0;i<=n*(n-1)/2;i++){
for(int j=1;j<=n;j++){
mn=min(mn,dp[sz][j][i]+max(0,(n-j)*(n-j-1)/2));
}
if(sz==0)mn=ans;
cout<<ans-mn<<" ";
}
cout<<endl;
/*
9
0 1 0 0 1 0 1 0 0
*/
return 0;
}