Jongmah Codeforces - 1110D

https://codeforces.com/contest/1110/problem/D

注意到3个完全相同的"连续三张"相当于3个"三张一样的牌",所以可以当成任意一种"连续三张"最多出2个,其他都出"三张一样的牌"

然后胡乱dp就可以了。。

然而我比赛时候30+分钟死活调不出来,成功爆零

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define fi first
 7 #define se second
 8 #define mp make_pair
 9 #define pb push_back
10 typedef long long ll;
11 typedef unsigned long long ull;
12 typedef pair<int,int> pi;
13 int ans[1000011][3][3];
14 int n,m,anss,num[1000011];
15 //用"顺子j"表示顺子(j-2,j-1,j)
16 //ans[i][j][k]表示位置i为止,顺子i取j个,顺子i-1取k个,且合法时最大答案 
17 int main()
18 {
19     int i,j,k,l,t;
20     scanf("%d%d",&n,&m);
21     for(i=1;i<=n;++i)
22     {
23         scanf("%d",&t);
24         ++num[t];
25     }
26     if(m>=3)
27     {
28         memset(ans,192,sizeof(ans));
29         ans[2][0][0]=0;
30         for(i=3;i<=m;++i)
31         {
32             for(j=0;j<=2;++j)
33             {
34                 for(k=0;k<=2;++k)
35                 {
36                     for(l=0;l<=2;++l)
37                     {
38                         if( (num[i-2]>=l+k+j) && (num[i-1]>=k+j) && (num[i]>=j) )
39                         {
40                             ans[i][j][k]=max(ans[i][j][k],ans[i-1][k][l]+j+(num[i-2]-l-k-j)/3);
41                         }
42                     }
43                 }
44             }
45         }
46         for(j=0;j<=2;++j)
47             for(k=0;k<=2;++k)
48                 anss=max(anss,ans[m][j][k]+(num[m]-j)/3+(num[m-1]-j-k)/3);
49         /*
50         for(i=3;i<=m;++i)
51         {
52             memset(tmp,192,sizeof(tmp));
53             for(j=0;j<=min(2,num[i-1]);++j)
54             {
55                 tmp[j][j]=ans[i-1][j][j];
56                 for(k=j+1;k<=min(6,num[i-2]);++k)
57                 {
58                     tmp[j][k]=max(tmp[j][k-1],ans[i-1][j][k]+(num[i-2]-k)/3);
59                 }
60             }
61             for(j=0;j<=min(2,num[i]);++j)
62             {
63                 for(k=j;k<=min(6,num[i-1]);++k)
64                 {
65                     //ans[i-1][k-j][?],?<=num[i-2]-j
66                     if(num[i-2]>=j && k-j<=2 && num[i-2]-j<=6)//&& (k-j)<=(num[i-2]-j) )
67                         ans[i][j][k]=tmp[k-j][num[i-2]-j]+j;
68                     
69                     for(l=0;l<=num[i-2]-j;++l)
70                     {
71                         ans[i][j][k]=max(ans[i][j][k],
72                             ans[i-1][k-j][l]+j);
73                     }
74                 }
75             }
76         }
77         for(j=0;j<=num[m];++j)
78             for(k=j;k<=num[m-1];++k)
79                 anss=max(anss,ans[m][j][k]+(num[m]-j)/3+(num[m-1]-k)/3);
80         */
81     }
82     else
83         anss=num[1]/3+num[2]/3;
84     printf("%d",anss);
85     return 0;
86 }
View Code

 

posted @ 2019-02-08 13:54  hehe_54321  阅读(323)  评论(0编辑  收藏  举报
AmazingCounters.com