題目鏈接:D. Jongmah
題目大意:一些數字,有兩種方式組成一個三元組(三角形),[x,x,x],[x,x+1,x+2],(刻子或順子)每個數字只能用一次,求最多組成多少三元組。
思路:顯然3個順子和3個刻子對結果的貢獻一樣,即3組[i,i+1,i+2]和[i,i,i],[i+1,i+1,i+1],[i+2,i+2,i+2]對答案的貢獻一樣。所以我們不妨假設每個以i爲開頭的三元組[i,i+1,i+2]不超過2個。設dp[i][t1][t2]表示前i個數值中,以有t1個三元組[i,i+1,i+2],t2個三元組[i-1i,i+1].(這裏對每個數值i只考慮兩種三元組,而不考慮[i-2,i-1,i]防止重複。)
轉移時枚舉第三種三元組情況即可,即枚舉[i-2,i-1,i]的數量t3,dp[i][t1][t2]=max(dp[i][t1][t2],dp[i][t2][t3]+(cnt[i]-t1-t2-t3)/3+t3);
代碼(採用了滾動數組):
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
typedef long long ll;
using namespace std;
#define INF 0x3f3f3f3f
const int mod=1e9+7;
const int maxn=1e6+10;
int n,m,cnt[maxn];
int dp[2][3][3];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int a;
scanf("%d",&a);
cnt[a]++;
}
memset(dp,-1,sizeof(dp));
dp[0][0][0]=0;
int tmp=1;
for(int i=1;i<=m;i++){
memset(dp[tmp],-1,sizeof(dp[tmp]));
for(int t1=0;t1<3;t1++)
for(int t2=0;t2<3;t2++)
for(int t3=0;t3<3;t3++){
if(cnt[i]-t1-t2-t3<0||dp[tmp^1][t2][t3]==-1)continue;
dp[tmp][t1][t2]=max(dp[tmp][t1][t2],dp[tmp^1][t2][t3]+(cnt[i]-t1-t2-t3)/3+t3);
}
tmp^=1;
}
printf("%d\n",dp[tmp^1][0][0]);
return 0;
}