版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/82052704
分析:
将目标转化一下,变为:求互不矛盾的数值相邻的三元组的个数
为什么是三元组呢,是因为这样第一个一定不能选最后一个,所以内部是不会矛盾的。在最优条件下,然后所有没用到数都可以自己选择自己,这样是没有贡献的。
矛盾的三元组只有一种情况:
即每一个位置相差1
这样无论指向顺序是 ,还是 都一定会矛盾(矛盾是指这个三元组指向的末端,与另一个三元组的始端相差不超过1)
定义
表示前i种值,第i种剩下j个的情况下,能凑出的最多三元组个数。
所以dp转移式就很显然了(
表示第i种元素的个数)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 400
using namespace std;
typedef long long ll;
int p[MAXN],cnt[MAXN];
int n,dp[MAXN][MAXN];
int main(){
while(SF("%d",&n)!=EOF){
memset(cnt,0,sizeof cnt);
for(int i=1;i<=n;i++){
SF("%d",&p[i]);
cnt[p[i]]++;
}
memset(dp,-1,sizeof dp);
dp[1][cnt[1]]=0;
dp[0][0]=0;
for(int i=2;i<=100;i++)
for(int j=0;j<=cnt[i];j++){
for(int k=0;k<=cnt[i-1];k++)
dp[i][j]=max(dp[i][j],dp[i-1][k]);
for(int k=0;k<=cnt[i-2];k++)
if(dp[i-2][k]!=-1)
dp[i][j]=max(dp[i][j],dp[i-2][k]+min(k,min(cnt[i-1],cnt[i]-j)));
}
int ans=0;
for(int i=0;i<=n;i++)
ans=max(ans,dp[100][i]);
PF("%d\n",ans);
}
}