Codeforces 1110D Jongmah dp

文章目录


链接

题意

一种麻将的牌从 1 → m 1 \to m 1m,给你一手牌, n n n张,求这手牌最多能组成面子的数量.

题解

标准dp,所以写一下博客.
可以发现同样三个数字组成的顺子不会超过三组(可以当作三个刻子处理),因此可以定义 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示前 i i i种牌, i − 1 , i , i + 1 i-1,i,i+1 i1,i,i+1组成的顺子数量为 j j j, i , i + 1 , i + 2 i,i+1,i+2 i,i+1,i+2组成的顺子数量为 k k k的最多面子数量.
转移的时候枚举 l , j , k l,j,k l,j,k分别表示最小数为 i − 2 , i − 1 , i i-2,i-1,i i2,i1,i的顺子数量.
此时转移方程为dp[i][j][k]=max(dp[i][j][k],dp[i-1][l][j]+k+(cnt[i]-j-k-l)/3);

const int yuzu=1e6;
typedef int fuko[yuzu|10];
fuko cnt,dp[3][3];
int main() {
    
    
  int i,n,m,j,k,l;
  read(n),read(m);
  for (i=1;i<=n;++i) ++cnt[read()];
  for (i=1;i<=m;++i) {
    
    
    for (j=0;j<3;++j) {
    
    
      for (k=0;k<3;++k) {
    
    
        for (l=0;l<3;++l) {
    
    
          if (cnt[i]>=j+k+l&&cnt[i+1]>=j+k&&cnt[i+2]>=k) 
            dp[j][k][i]=max(dp[j][k][i],dp[l][j][i-1]+k+(cnt[i]-j-k-l)/3); 
            // 借助i,i+1,i+2能够形成k个顺子,此时j+k+l个i已经被顺子用掉,剩下的i三个组成刻子
        }
      }
    }
  }
  printf("%d\n",dp[0][0][m]);//由于cnt[m+1]肯定为0,不需要考虑m的顺子数.
}

Thank you.

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/108906073