Codeforces Global Round 1 - D. Jongmah(动态规划)

Problem   Codeforces Global Round 1 - D. Jongmah

Time Limit: 3000 mSec

Problem Description

 

Input

 

Output

 Print one integer: the maximum number of triples you can form.

Sample Input

10 6
2 3 3 3 4 4 4 5 5 6

Sample Output

3

 

题解:动态规划,对这种状态定义不熟悉,主要还是没有发现最优方案所具有的性质,其实个人感觉dp往往是在一定的观察的基础上进行的,发现最优结果所必须具有的一些特征,然后利用这种特征减少状态总数,使得dp能够进行。这道题的一个性质就是我们可以让最优结果中对每个i,不会出现三个及三个以上(i, i+1, i+2)型的三元组,因为这样的三元组可以被3个i,3个i+1,3个i+2所替代,而不产生任何影响,这样一来我们就可以对每个i,枚举它所组成的三元组的个数,具体状态定义:

  dp[i][j][k],考虑前i种数,(i-1, i, i+1)有j个,(i, i+1, i+2),有k个的最多三元组数

不记录(i-2, i-1, i)的个数是因为在状态转移时用不到,用dp[i][j][k]更行dp[i+1][k][t]即可。转移方程很简单,详见代码。

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define REP(i, n) for (int i = 1; i <= (n); i++)
 6 #define sqr(x) ((x) * (x))
 7 
 8 const int maxn = 1000000 + 100;
 9 const int maxm = 200000 + 100;
10 const int maxs = 10000 + 10;
11 
12 typedef long long LL;
13 typedef pair<int, int> pii;
14 typedef pair<double, double> pdd;
15 
16 const LL unit = 1LL;
17 const int INF = 0x3f3f3f3f;
18 const double eps = 1e-14;
19 const double inf = 1e15;
20 const double pi = acos(-1.0);
21 const int SIZE = 100 + 5;
22 const LL MOD = 1000000007;
23 
24 int n, m;
25 int a[maxn];
26 int dp[maxn][3][3];
27 
28 int main()
29 {
30     ios::sync_with_stdio(false);
31     cin.tie(0);
32     //freopen("input.txt", "r", stdin);
33     //freopen("output.txt", "w", stdout);
34     cin >> n >> m;
35     int x;
36     for (int i = 0; i < n; i++)
37     {
38         cin >> x;
39         a[x]++;
40     }
41     memset(dp, -INF, sizeof(dp));
42     dp[0][0][0] = 0;
43     for (int i = 0; i <= m; i++)
44     {
45         for (int j = 0; j < 3; j++)
46         {
47             for (int k = 0; k < 3; k++)
48             {
49                 int lim = a[i + 1] - j - k;
50                 if (lim < 0)
51                     continue;
52                 for (int t = 0; t < 3 && t <= lim; t++)
53                 {
54                     dp[i + 1][k][t] = max(dp[i + 1][k][t], dp[i][j][k] + t + (lim - t) / 3);
55                 }
56             }
57         }
58     }
59     cout << dp[m + 1][0][0] << endl;
60     return 0;
61 }

 

posted on 2019-04-29 21:16  随缘&不屈  阅读(289)  评论(0编辑  收藏  举报

导航