codefroces 1420 E. Battle Lemmings

2020-09-28 09:10:28

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;
}