如果能够发现一点转化的话就简单很多
比如说最后的答案里出现了
三个(a,a+1,a+2),我们可以将它看作是(a,a,a),(a+1,a+1,a+1),(a+2,a+2,a+2)
也就是每种三元组(除了(a,a,a))最多只会出现两次
那么每种数最多有6个是个其它数组成三元组。
直接dp即可
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define fo(i,a,b) for (int (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (int (i)=(b);(i)>=(a);(i)--)
#define mk(x,y) make_pair((x),(y))
using namespace std;
typedef double db;
typedef long long ll;
const int N=1e6+5;
int c[N],r[N];
int f[N][7][7],n,m,x,ans,tot;
bool bz[N][7][7];
void cmax(int &x,int y){
x=max(x,y);
}
int main()
{
// freopen("data.in","r",stdin);
scanf("%d %d",&n,&m);
fo(i,1,n) scanf("%d",&x), c[x]++;
fo(i,1,m) {
if (c[i]>=6) {
tot+=(c[i]-6)/3;
r[i]=(c[i]-6)%3;
c[i]=6;
}
}
// fo(i,1,m) printf("%d %d\n",r[i],c[i]);
int z=0;
bz[0][0][0]=1;
fo(i,1,m) {
fo(j,0,6) fo(k,0,6) { //
if (!bz[i-1][j][k]) continue;
fo(l,0,c[i]) {
int d=min(l,min(j,k));
if (i>=3) {
z=(k-d+r[i-2])/3;
}
else z=0;
cmax(f[i][c[i]-d][j-d], f[i-1][j][k]+d+z);
bz[i][c[i]-d][j-d]=1;
}
}
}
z=0;
fo(i,0,6) fo(j,0,6) {
if (bz[m][i][j]) {
z=(i+r[m])/3+(j+r[m-1])/3;
ans=max(ans, f[m][i][j]+z);
}
}
printf("%d",ans+tot);
return 0;
}
标签:int,Jongmah,tot,ans,include,cf1110D,bz,fo
From: https://www.cnblogs.com/ganking/p/17744384.html