1. 程式人生 > >CF 1110 D. Jongmah

CF 1110 D. Jongmah

ostream cstring include type const ons == title 代碼

D. Jongmah

鏈接

題意:

  一些數字,有兩種方式組成一個三元組,[x,x,x],[x,x+1,x+2],每個數字只能用一次,求最多組成多少三元組。

分析:

  因為每三個[x,x+1,x+2]是可以拆成[x,x,x],[x+1,x+1,x+1],[x+2,x+2,x+2]的,所以可以認為對於以x開始的[x,x+1,x+2]最多有兩個。

  於是可以dp[i][x][y]表示到第i個數字,存在x個[i-1,i,i+1],y個[i,i+1,i+2],最多組成多少個三元組(這些三元組的右端點在i以內,超出i三元組有x+y個,沒有記錄到裏面)

  然後轉移的時候枚舉多少個[i+1,i+2,i+3]。

代碼:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;

inline 
int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-0;return x*f; } const int N = 1e6 + 10; LL f[N][3][3], a[N]; int main() { int n = read(), m = read(); for (int i = 1; i <= n; ++i) a[read()] ++; memset(f,
-0x3f, sizeof(f)); f[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; f[i][x][y] = max(f[i][x][y], f[i - 1][z][x] + (a[i] - x - y - z) / 3 + z); } } cout << f[m][0][0]; return 0; }

CF 1110 D. Jongmah