• [GXOI/GZOI2019]宝牌一大堆(dp)


    [GXOI/GZOI2019]宝牌一大堆(dp)

    luogu     bzoj

    这个麻将题还算挺友善的,比隔壁zjoi的要好得多。。。

    比较正常的做法是五维dp

    但事实上六维dp也是完全不会被卡的

    七对子选权值最高的七个,国士无双直接$13^2$暴力

    $dp[i][j][0/1][k][l][m]$表示枚举到了第i张牌,已经凑了j个面子,有无雀头,第i张牌已经用了k张,第i+1张牌用了l张,第i+2张牌用了m张,直接暴力转移。。。

    然后你会得到50...

    当然需要优化。

    优化1:

    枚举到dp值为0的直接continue,这样的不合法牌型有很多可以直接跳过。

    优化2:

    l和m只枚举到2,原因?如果枚举到三个顺子的话那么我们完全可以用三个刻子等效替代。

    优化3:

    不需要考虑杠。

    原因?

    $C_{4}^{3}=4$,$C_{4}^{4}=1$

    就算这张牌是宝牌选刻子也必然优于杠子

    代码就领略一下精神吧(

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<queue>
      4 #define d01(x) for(int x=0;x<2;x++)
      5 using std::priority_queue;
      6 using std::max;
      7 typedef long long lint;
      8 char si[3];
      9 void dm(lint &kk,lint l){kk=max(kk,l);}
     10 
     11 int a[35],dora[35];//1~9,10~18,19~27,28,29,30,31,32,33,34
     12 lint dp[36][5][2][5][3][3];
     13 lint dg[36];
     14 lint ans;
     15 int c[5][5]={
     16     1,0,0,0,0,
     17     1,1,0,0,0,
     18     1,2,1,0,0,
     19     1,3,3,1,0,
     20     1,4,6,4,1
     21 };
     22 int yaoku[15]={0,1,9,10,18,19,27,28,29,30,31,32,33,34};
     23 bool isyaoku[35]={0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1};
     24 bool tail[35]={0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1};
     25 void kokushi()
     26 {
     27     int x;
     28     for(int i=1;i<=13;i++)
     29     {
     30         x=yaoku[i];
     31         lint tmp=13;
     32         tmp*=c[a[x]][2]*dora[x]*dora[x];
     33         for(int j=1;j<=13;j++)
     34         {
     35             if(i==j) continue;x=yaoku[j];
     36             tmp*=a[x]*dora[x];
     37         }
     38         ans=max(ans,tmp);
     39     }
     40 }
     41 priority_queue<int> q;
     42 void chitoi()
     43 {
     44     lint tmp=7;
     45     for(int i=1;i<=34;i++) q.push(c[a[i]][2]*dora[i]*dora[i]);
     46     int g;
     47     for(int i=1;i<=7;i++)
     48     {
     49         g=q.top();
     50         q.pop();
     51         tmp*=g;
     52     }
     53     ans=max(ans,tmp);
     54     while(!q.empty()) q.pop();
     55 }
     56 
     57 
     58 void clr()
     59 {
     60     for(int i=1;i<=35;i++)
     61     {
     62         dg[i]=0;
     63         for(int j=0;j<=4;j++)
     64         {
     65             for(int k=0;k<=4;k++)
     66             {
     67                 for(int l=0;l<=2;l++)
     68                 {
     69                     for(int m=0;m<=2;m++)
     70                     dp[i][j][0][k][l][m]=dp[i][j][1][k][l][m]=0;
     71                 }
     72             }
     73         }
     74     }
     75     for(int i=1;i<=34;i++) a[i]=4,dora[i]=1;
     76     ans=0;
     77     dp[1][0][0][0][0][0]=1;
     78 }
     79 int main()
     80 {
     81     int T;
     82     scanf("%d",&T);
     83     while(T--)
     84     {
     85         clr();
     86         while(1)
     87         {
     88             scanf("%s",si);
     89             if(si[0]=='0') break;
     90             else if(si[1]=='p') a[si[0]-'0']--;
     91             else if(si[1]=='s') a[si[0]-'0'+9]--;
     92             else if(si[1]=='m') a[si[0]-'0'+18]--;
     93             else if(si[0]=='E') a[28]--;
     94             else if(si[0]=='S') a[29]--;
     95             else if(si[0]=='W') a[30]--;
     96             else if(si[0]=='N') a[31]--;
     97             else if(si[0]=='B') a[32]--;
     98             else if(si[0]=='F') a[33]--;
     99             else if(si[0]=='Z') a[34]--;
    100         }
    101         while(1)
    102         {
    103             scanf("%s",si);
    104             if(si[0]=='0') break;
    105             else if(si[1]=='p') dora[si[0]-'0']=2;
    106             else if(si[1]=='s') dora[si[0]-'0'+9]=2;
    107             else if(si[1]=='m') dora[si[0]-'0'+18]=2;
    108             else if(si[0]=='E') dora[28]=2;
    109             else if(si[0]=='S') dora[29]=2;
    110             else if(si[0]=='W') dora[30]=2;
    111             else if(si[0]=='N') dora[31]=2;
    112             else if(si[0]=='B') dora[32]=2;
    113             else if(si[0]=='F') dora[33]=2;
    114             else if(si[0]=='Z') dora[34]=2;
    115         }
    116         kokushi();//国士无双 
    117         chitoi();//七对子 
    118         for(int i=1;i<=34;i++)
    119         {
    120             for(int j=0;j<=4;j++)
    121             {
    122                 for(int k=0;k<=4;k++)
    123                 {
    124                     for(int l=0;l<=2;l++)
    125                     {
    126                         for(int m=0;m<=2;m++)
    127                         {
    128                             if(!dp[i][j][0][k][l][m]&&!dp[i][j][1][k][l][m]) continue;
    129                             if(a[i]-k>=2) dm(dp[i][j][1][k+2][l][m],dp[i][j][0][k][l][m]/c[a[i]][k]*c[a[i]][k+2]*dora[i]*dora[i]);
    130                             //雀头 
    131                             if(j<4)
    132                             {
    133                                 if(a[i]-k>=3) d01(o) dm(dp[i][j+1][o][k+3][l][m],dp[i][j][o][k][l][m]/c[a[i]][k]*c[a[i]][k+3]*dora[i]*dora[i]*dora[i]);
    134                                 //刻子 
    135                                 if((!tail[i])&&a[i]-k>0&&a[i+1]-l>0&&a[i+2]-m>0&&l!=2&&m!=2)
    136                                     d01(o) dm(dp[i][j+1][o][k+1][l+1][m+1],dp[i][j][o][k][l][m]/c[a[i]][k]*c[a[i]][k+1]*dora[i]/c[a[i+1]][l]*c[a[i+1]][l+1]*dora[i+1]/c[a[i+2]][m]*c[a[i+2]][m+1]*dora[i+2]);
    137                                 //顺子 
    138                             }
    139                             dm(dp[i+1][j][0][l][m][0],dp[i][j][0][k][l][m]);
    140                             dm(dp[i+1][j][1][l][m][0],dp[i][j][1][k][l][m]);
    141                             //转移 
    142                             if(j==4) dg[i]=max(dg[i],dp[i][j][1][k][l][m]);
    143                         }
    144                     }
    145                 }
    146             }
    147         }
    148         for(int i=1;i<=35;i++) ans=max(ans,dg[i]);
    149         printf("%lld
    ",ans);
    150     }
    151     return 0;
    152 }
    Orz
  • 相关阅读:
    哈夫曼编码
    20182330《程序设计与设计结构》 第九周学习总结
    20182330 2019-2020-1 《数据结构与面向对象程序设计》实验七报告
    20182330 2019-2020-1 《数据结构与面向对象程序设计》实验八报告
    20182330《程序设计与设计结构》 第八周学习总结
    20182330《程序设计与设计结构》 第七周学习总结
    20182330 2019-2020-1 《数据结构与面向对象程序设计》实验六报告
    20182326 2018-2019-1《程序设计与数据结构》课程总结
    20182326 2019-2020-1 《数据结构与面向对象程序设计》实验九报告
    团队作业——学习心得
  • 原文地址:https://www.cnblogs.com/rikurika/p/11047183.html
Copyright © 2020-2023  润新知