- 题目链接:http://codeforces.com/contest/1110/problem/D
- 题意:给你两个整数n、m,表示:给你n个整数,每个整数的范围都在[1 , m]。现在可以将三个数值相同的数(如:777)或者三个数值连续的数(如:123,但112不算)组成一个三元组,问这n个数最多能组多少个三元组?(每个数最多只能用在一个三元组中)
- 因为3个连续三元组可以转换成三个相同数值的三元组,所以对于一种连续三元组,其个数最多有2个。那么对于一个数值等于 i的数(可能有多个数的数值等于i),其除了组成相同数的三元组以外,组成了x个[i-2, i-1, i],y个[i-1, i, i+1], z个[i, i+1, i+2] (0<= x,y,z <=2),这是对于数值i的所有情况,也就是对于数值i的所有可能的状态。那么设dp[i][y][z]表示在组成y个[i-1, i, i+1], z个[i, i+1, i+2] 的状态下,在只使用小于等于数值i的数时(1<= i <= m)(也就是dp[i][y][z]的值并没有算上这 y+z 个三元组),最多组成了多少个三元组
- 注意点:要把dp初始化为 负无穷,表示此种情况不存在。令dp[0][0][0] = 0,表示此种情况存在,但数量为0。
#include <bits/stdc++.h>
#define pi acos(-1.0 )
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn =1e6 + 10;
const LL mod = 1e9+7;
int a[maxn], dp[maxn][3][3];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
int tmp;
for(int i=1; i<=n; i++){
scanf("%d", &tmp);
a[tmp]++;
}
memset(dp, -INF, sizeof(dp));
dp[0][0][0] = 0;
for(int i=1; i<=m; i++){
for(int x=0; x<3; x++){
for(int y=0; y<3; y++){
for(int z=0; z<3; z++){
if(a[i] < x+y+z) continue;
dp[i][y][z] = max(dp[i][y][z], dp[i-1][x][y] + (a[i]-x-y-z)/3 + x);
}
}
}
}
printf("%d\n", dp[m][0][0]);
}