zoukankan      html  css  js  c++  java
  • 设计模式之状态模式20170712

    行为型设计模式之状态模式:

    一、含义

    为每个状态创建与之对应的类(对应的每个类实现同一个接口或继承同一个抽象类,便于统一处理),并且再通过一个类切换状态

    二、代码说明

    1.一般包含三个角色抽象状态角色,具体状态角色,以及环境(上下文)角色(负责具体状态的切换)。

    具体步骤:

    1)定义环境角色,并初始化状态

    2)通过环境角色执行行为,同时也就是对应状态的行为被执行

    3)对应状态的行为的执行分为两种情况:

    I、对应状态对应行为执行后,环境角色继续执行行为,调用的还是此状态,此状态的下一个行为(下一状态的行为)被执行,执行中会设置下一态(设置下一态一般都放在抽象父类中,同时由于是继承设置下一态时,也要把对应的环境对象设置进去(继承导致每个子类都有对应的环境类的引用),这样下一个状态对象才能调用环境类中的函数),设置完后再执行对应的下一个行为

    II、或对应状态对应行为(函数)执行中,先执行对应的操作,然后设置下一态(显然也要把对应的环境对象设置进去),这样环境角色再次执行行为就是调用下一态的行为(函数)了,而不是还停留在本状态。

    两种情况均可以,二选一即可,但是显然第二种方式更简单一点,但对外来看没有差异。

    4)接下来再次调用环境角色执行行为,由于前面设置了状态,此时执行的就是下一状态的行为

    5)不断调用环境角色执行行为,知道所有的状态行为执行完毕

    6)扩展:不断调用环境角色执行行为可以使用建造者模式组装起来进行优化

    2.在用C实现过程中也是参考这种思想,不过设置下一态不使用继承的方式,以电梯运行状态举例,状态迁移表如下:

     

    具体实现如下:

    1)状态模式使用场景:

     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     StatePatternUsage.c
     5 * Description        :     状态模式的使用
     6 
     7 book@book-desktop:/work/projects/test/DesignPatterns$ gcc -o StatePatternUsage RunningState.c StoppingState.c  OpenningState.c ClosingState.c StatePattern.c StatePatternUsage.c 
     8 book@book-desktop:/work/projects/test/DesignPatterns$ ./StatePatternUsage 
     9 Lift door open!
    10 Lift door close!
    11 Lift door run!
    12 Lift door stop!
    13 
    14 * Created            :     2017.07.12.
    15 * Author            :     Yu Weifeng
    16 * Function List         :     
    17 * Last Modified     :     
    18 * History            :     
    19 ******************************************************************************/
    20 #include"stdio.h"
    21 #include"malloc.h"
    22 #include"stdlib.h"
    23 #include"string.h"
    24 #include"StatePattern.h"
    25 
    26 
    27 
    28 
    29 /*****************************************************************************
    30 -Fuction        : main
    31 -Description    : 
    32 -Input            : 
    33 -Output         : 
    34 -Return         : 
    35 * Modify Date      Version         Author           Modification
    36 * -----------------------------------------------
    37 * 2017/07/12    V1.0.0         Yu Weifeng       Created
    38 ******************************************************************************/
    39 int main(int argc,char **argv)
    40 {
    41      T_StateContext tStateContext=newStateContext;
    42     T_State tState=newClosingState;
    43     tStateContext.SetState(&tState);
    44 
    45     tStateContext.Open();
    46     tStateContext.Close();
    47     tStateContext.Run();
    48     tStateContext.Stop();
    49 
    50     
    51     return 0;
    52 }
    StatePatternUsage.c

    隐藏(封装)了状态的变化过程,它的切换引起了行为的变化。对外来说,我们只看到行为的发生改变,而不用知道是状态变化引起的。

    2)被调用者:

    I、环境(上下文)角色(负责具体状态的切换):

      1 /*****************************************************************************
      2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
      3 ------------------------------------------------------------------------------
      4 * File Module        :     StatePattern.c
      5 * Description        :     状态模式
      6                         对各个状态进行管理,也可以改名为StateManage.c
      7                         为统一名称,本文件也是状态模式的核心故还是
      8                         命名为StatePattern.c
      9                         
     10                         
     11 * Created            :     2017.07.12.
     12 * Author            :     Yu Weifeng
     13 * Function List         :     
     14 * Last Modified     :     
     15 * History            :     
     16 ******************************************************************************/
     17 #include"stdio.h"
     18 #include"malloc.h"
     19 #include"stdlib.h"
     20 #include"string.h"
     21 #include"StatePattern.h"
     22 
     23 
     24 
     25 static T_State g_tState;
     26 
     27 /*****************************************************************************
     28 -Fuction        : SetState
     29 -Description    : 公有函数
     30 -Input            : 
     31 -Output         : 
     32 -Return         : 
     33 * Modify Date      Version         Author           Modification
     34 * -----------------------------------------------
     35 * 2017/07/12      V1.0.0         Yu Weifeng       Created
     36 ******************************************************************************/
     37 void SetState(T_State *i_ptState)
     38 {
     39     memcpy(&g_tState,i_ptState,sizeof(T_State));
     40 }
     41 
     42 /*****************************************************************************
     43 -Fuction        : SetState
     44 -Description    : 公有函数
     45 -Input            : 
     46 -Output         : 
     47 -Return         : 
     48 * Modify Date      Version         Author           Modification
     49 * -----------------------------------------------
     50 * 2017/07/12      V1.0.0         Yu Weifeng       Created
     51 ******************************************************************************/
     52 void GetState(T_State *o_ptState)
     53 {
     54     memcpy(o_ptState,&g_tState,sizeof(T_State));
     55 }
     56 /*****************************************************************************
     57 -Fuction        : Open
     58 -Description    : 公有函数
     59 -Input            : 
     60 -Output         : 
     61 -Return         : 
     62 * Modify Date      Version         Author           Modification
     63 * -----------------------------------------------
     64 * 2017/07/12      V1.0.0         Yu Weifeng       Created
     65 ******************************************************************************/
     66 void Open()
     67 {
     68     g_tState.Open();
     69 }
     70 /*****************************************************************************
     71 -Fuction        : Close
     72 -Description    : 公有函数
     73 -Input            : 
     74 -Output         : 
     75 -Return         : 
     76 * Modify Date      Version         Author           Modification
     77 * -----------------------------------------------
     78 * 2017/07/12      V1.0.0         Yu Weifeng       Created
     79 ******************************************************************************/
     80 void Close()
     81 {
     82     g_tState.Close();
     83 }
     84 /*****************************************************************************
     85 -Fuction        : Run
     86 -Description    : 公有函数
     87 -Input            : 
     88 -Output         : 
     89 -Return         : 
     90 * Modify Date      Version         Author           Modification
     91 * -----------------------------------------------
     92 * 2017/07/12      V1.0.0         Yu Weifeng       Created
     93 ******************************************************************************/
     94 void Run()
     95 {
     96     g_tState.Run();
     97 }
     98 /*****************************************************************************
     99 -Fuction        : Stop
    100 -Description    : 公有函数
    101 -Input            : 
    102 -Output         : 
    103 -Return         : 
    104 * Modify Date      Version         Author           Modification
    105 * -----------------------------------------------
    106 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    107 ******************************************************************************/
    108 void Stop()
    109 {
    110     g_tState.Stop();
    111 }
    StatePattern.c
     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     StatePattern.h
     5 * Description        :     状态模式
     6                         对各个状态进行管理,也可以改名为StateManage.h
     7                         为统一名称,本文件也是状态模式的核心故还是
     8                         命名为StatePattern.h
     9 * Created            :     2017.07.12.
    10 * Author            :     Yu Weifeng
    11 * Function List         :     
    12 * Last Modified     :     
    13 * History            :     
    14 ******************************************************************************/
    15 #ifndef STATE_PATTERN_H
    16 #define STATE_PATTERN_H
    17 
    18 
    19 
    20 typedef struct State//以电梯运行四种状态举例
    21 {
    22 //    T_FatherState tFatherState;//继承父类,由于c中没有super关键字
    23     void (*Open)();//子类内部函数要初始化后才能使用父类的,除非初始化后再设置状态
    24     void (*Close)();//为了封装,内部函数就直接调用上下文类设置状态,不使用继承
    25     void (*Run)();//也是由于C中只有一个上下文Context,才可以这么做
    26     void (*Stop)();
    27 }T_State;//对各种状态的行为进行抽象后的抽象接口
    28 
    29 typedef struct FatherState//抽象出子类统一会设置上下状态函数
    30 {
    31 //void (*SetContext)(T_StateContext *i_ptStateContext);//由于面向对象语言中
    32 //每个子类new的时候都会有一个Context引用产生,切换状态时,
    33 //就需要要设置context(下一个子类才能使用context来设置下一态),
    34 //而C中只有一个,所以不需要
    35     void (*SetState)(T_State *i_ptState);//供状态设置下一状态使用
    36     void (*GetState)(T_State *o_ptState);
    37 }T_FatherState;
    38 
    39 typedef struct StateContext//因为状态需要切换所以需要上下文类
    40 {
    41     void (*SetState)(T_State *i_ptState);//供状态设置下一状态使用
    42     void (*GetState)(T_State *o_ptState);
    43     void (*Open)();//内部不加入状态的静态对象,因为增加的话结构体会过于臃肿
    44     void (*Close)();//而且不加入使用更灵活,同时C的对象都是函数指针不费内存
    45     void (*Run)();
    46     void (*Stop)();
    47 }T_StateContext;
    48 
    49 
    50 
    51 
    52 
    53 
    54 void SetState(T_State *i_ptState);
    55 void GetState(T_State *o_ptState);
    56 void Open();
    57 void Close();
    58 void Run();
    59 void Stop();
    60 #define newStateContext {SetState,GetState,Open,Close,Run,Stop};
    61 
    62 
    63 
    64 
    65 
    66 void RunningStateOpen();
    67 void RunningStateClose();
    68 void RunningStateRun();
    69 void RunningStateStop();
    70 #define newRunningState {RunningStateOpen,RunningStateClose,RunningStateRun,RunningStateStop}
    71 
    72 void StoppingStateOpen();
    73 void StoppingStateClose();
    74 void StoppingStateRun();
    75 void StoppingStateStop();
    76 #define newStoppingState {StoppingStateOpen,StoppingStateClose,StoppingStateRun,StoppingStateStop}
    77 
    78 void ClosingStateOpen();
    79 void ClosingStateClose();
    80 void ClosingStateRun();
    81 void ClosingStateStop();
    82 #define newClosingState {ClosingStateOpen,ClosingStateClose,ClosingStateRun,ClosingStateStop}
    83 
    84 void OpenningStateOpen();
    85 void OpenningStateClose();
    86 void OpenningStateRun();
    87 void OpenningStateStop();
    88 #define newOpenningState {OpenningStateOpen,OpenningStateClose,OpenningStateRun,OpenningStateStop}
    89 
    90 
    91 
    92 #endif
    StatePattern.h

    II、具体状态角色(各个状态实现同一个接口)

     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     ClosingState.c
     5 * Description        :     关闭状态下的各种行为
     6 * Created            :     2017.07.12.
     7 * Author            :     Yu Weifeng
     8 * Function List         :     
     9 * Last Modified     :     
    10 * History            :     
    11 ******************************************************************************/
    12 #include"stdio.h"
    13 #include"malloc.h"
    14 #include"stdlib.h"
    15 #include"string.h"
    16 #include"StatePattern.h"
    17 
    18 
    19 
    20 
    21 
    22 /*****************************************************************************
    23 -Fuction        : ClosingStateOpen
    24 -Description    : 公有函数
    25 -Input            : 
    26 -Output         : 
    27 -Return         : 
    28 * Modify Date      Version         Author           Modification
    29 * -----------------------------------------------
    30 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    31 ******************************************************************************/
    32 void ClosingStateOpen()
    33 {
    34     T_StateContext tStateContext=newStateContext;
    35     T_State tState=newOpenningState;
    36     tStateContext.SetState(&tState);//切换状态
    37     tStateContext.GetState(&tState);
    38     tState.Open();//执行,逻辑上过度 到下一态
    39 }
    40 /*****************************************************************************
    41 -Fuction        : ClosingStateClose
    42 -Description    : 公有函数
    43 -Input            : 
    44 -Output         : 
    45 -Return         : 
    46 * Modify Date      Version         Author           Modification
    47 * -----------------------------------------------
    48 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    49 ******************************************************************************/
    50 void ClosingStateClose()
    51 {
    52     printf("Lift door close!
    ");
    53 }
    54 /*****************************************************************************
    55 -Fuction        : ClosingStateRun
    56 -Description    : 公有函数
    57 -Input            : 
    58 -Output         : 
    59 -Return         : 
    60 * Modify Date      Version         Author           Modification
    61 * -----------------------------------------------
    62 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    63 ******************************************************************************/
    64 void ClosingStateRun()
    65 {
    66     T_StateContext tStateContext=newStateContext;
    67     T_State tState=newRunningState;
    68     tStateContext.SetState(&tState);//切换状态
    69     tStateContext.GetState(&tState);
    70     tState.Run();//执行,逻辑上过度 到下一态
    71 }
    72 /*****************************************************************************
    73 -Fuction        : ClosingStateStop
    74 -Description    : 公有函数
    75 -Input            : 
    76 -Output         : 
    77 -Return         : 
    78 * Modify Date      Version         Author           Modification
    79 * -----------------------------------------------
    80 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    81 ******************************************************************************/
    82 void ClosingStateStop()
    83 {
    84     T_StateContext tStateContext=newStateContext;
    85     T_State tState=newStoppingState;
    86     tStateContext.SetState(&tState);//切换状态
    87     tStateContext.GetState(&tState);
    88     tState.Stop();//执行,逻辑上过度 到下一态
    89 }
    ClosingState.c
     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     OpenningState.c
     5 * Description        :     开门状态下的各种行为
     6 * Created            :     2017.07.12.
     7 * Author            :     Yu Weifeng
     8 * Function List         :     
     9 * Last Modified     :     
    10 * History            :     
    11 ******************************************************************************/
    12 #include"stdio.h"
    13 #include"malloc.h"
    14 #include"stdlib.h"
    15 #include"string.h"
    16 #include"StatePattern.h"
    17 
    18 
    19 
    20 
    21 
    22 /*****************************************************************************
    23 -Fuction        : OpenningStateOpen
    24 -Description    : 公有函数
    25 -Input            : 
    26 -Output         : 
    27 -Return         : 
    28 * Modify Date      Version         Author           Modification
    29 * -----------------------------------------------
    30 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    31 ******************************************************************************/
    32 void OpenningStateOpen()
    33 {
    34     printf("Lift door open!
    ");
    35 }
    36 /*****************************************************************************
    37 -Fuction        : OpenningStateClose
    38 -Description    : 公有函数
    39 -Input            : 
    40 -Output         : 
    41 -Return         : 
    42 * Modify Date      Version         Author           Modification
    43 * -----------------------------------------------
    44 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    45 ******************************************************************************/
    46 void OpenningStateClose()
    47 {
    48     T_StateContext tStateContext=newStateContext;
    49     T_State tState=newClosingState;
    50     tStateContext.SetState(&tState);//切换状态
    51     tStateContext.GetState(&tState);
    52     tState.Close();//执行,逻辑上过度 到下一态
    53 }
    54 /*****************************************************************************
    55 -Fuction        : OpenningStateRun
    56 -Description    : 门开肯定不运行
    57 -Input            : 
    58 -Output         : 
    59 -Return         : 
    60 * Modify Date      Version         Author           Modification
    61 * -----------------------------------------------
    62 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    63 ******************************************************************************/
    64 void OpenningStateRun()
    65 {
    66 
    67 }
    68 /*****************************************************************************
    69 -Fuction        : OpenningStateStop
    70 -Description    : 门开肯定停止了
    71 -Input            : 
    72 -Output         : 
    73 -Return         : 
    74 * Modify Date      Version         Author           Modification
    75 * -----------------------------------------------
    76 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    77 ******************************************************************************/
    78 void OpenningStateStop()
    79 {
    80 
    81 }
    OpenningState.c
     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     RunningState.c
     5 * Description        :     运行状态下的各种行为
     6 * Created            :     2017.07.12.
     7 * Author            :     Yu Weifeng
     8 * Function List         :     
     9 * Last Modified     :     
    10 * History            :     
    11 ******************************************************************************/
    12 #include"stdio.h"
    13 #include"malloc.h"
    14 #include"stdlib.h"
    15 #include"string.h"
    16 #include"StatePattern.h"
    17 
    18 
    19 
    20 
    21 
    22 /*****************************************************************************
    23 -Fuction        : RunningStateOpen
    24 -Description    : 运行不能打开
    25 -Input            : 
    26 -Output         : 
    27 -Return         : 
    28 * Modify Date      Version         Author           Modification
    29 * -----------------------------------------------
    30 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    31 ******************************************************************************/
    32 void RunningStateOpen()
    33 {
    34 }
    35 /*****************************************************************************
    36 -Fuction        : RunningStateClose
    37 -Description    : 运行肯定关闭
    38 -Input            : 
    39 -Output         : 
    40 -Return         : 
    41 * Modify Date      Version         Author           Modification
    42 * -----------------------------------------------
    43 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    44 ******************************************************************************/
    45 void RunningStateClose()
    46 {
    47 
    48 }
    49 /*****************************************************************************
    50 -Fuction        : RunningStateRun
    51 -Description    : 公有函数
    52 -Input            : 
    53 -Output         : 
    54 -Return         : 
    55 * Modify Date      Version         Author           Modification
    56 * -----------------------------------------------
    57 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    58 ******************************************************************************/
    59 void RunningStateRun()
    60 {
    61     printf("Lift door run!
    ");
    62 }
    63 /*****************************************************************************
    64 -Fuction        : RunningStateStop
    65 -Description    : 公有函数
    66 -Input            : 
    67 -Output         : 
    68 -Return         : 
    69 * Modify Date      Version         Author           Modification
    70 * -----------------------------------------------
    71 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    72 ******************************************************************************/
    73 void RunningStateStop()
    74 {
    75     T_StateContext tStateContext=newStateContext;
    76     T_State tState=newStoppingState;
    77     tStateContext.SetState(&tState);//切换状态
    78     tStateContext.GetState(&tState);
    79     tState.Stop();//执行,逻辑上过度 到下一态
    80 }
    RunningState.c
     1 /*****************************************************************************
     2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
     3 ------------------------------------------------------------------------------
     4 * File Module        :     StoppingState.c
     5 * Description        :     停止状态下的各种行为
     6 * Created            :     2017.07.12.
     7 * Author            :     Yu Weifeng
     8 * Function List         :     
     9 * Last Modified     :     
    10 * History            :     
    11 ******************************************************************************/
    12 #include"stdio.h"
    13 #include"malloc.h"
    14 #include"stdlib.h"
    15 #include"string.h"
    16 #include"StatePattern.h"
    17 
    18 
    19 
    20 
    21 
    22 /*****************************************************************************
    23 -Fuction        : StoppingStateOpen
    24 -Description    : 公有函数
    25 -Input            : 
    26 -Output         : 
    27 -Return         : 
    28 * Modify Date      Version         Author           Modification
    29 * -----------------------------------------------
    30 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    31 ******************************************************************************/
    32 void StoppingStateOpen()
    33 {
    34     T_StateContext tStateContext=newStateContext;
    35     T_State tState=newOpenningState;
    36     tStateContext.SetState(&tState);//切换状态
    37     tStateContext.GetState(&tState);
    38     tState.Open();//执行,逻辑上过度 到下一态
    39 
    40 }
    41 /*****************************************************************************
    42 -Fuction        : StoppingStateClose
    43 -Description    : 停止本来门就是关的
    44 -Input            : 
    45 -Output         : 
    46 -Return         : 
    47 * Modify Date      Version         Author           Modification
    48 * -----------------------------------------------
    49 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    50 ******************************************************************************/
    51 void StoppingStateClose()
    52 {
    53 
    54 }
    55 /*****************************************************************************
    56 -Fuction        : StoppingStateRun
    57 -Description    : 停止接下来再运行
    58 -Input            : 
    59 -Output         : 
    60 -Return         : 
    61 * Modify Date      Version         Author           Modification
    62 * -----------------------------------------------
    63 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    64 ******************************************************************************/
    65 void StoppingStateRun()
    66 {
    67     T_StateContext tStateContext=newStateContext;
    68     T_State tState=newRunningState;
    69     tStateContext.SetState(&tState);//切换状态
    70     tStateContext.GetState(&tState);
    71     tState.Run();//执行,逻辑上过度 到下一态
    72 }
    73 /*****************************************************************************
    74 -Fuction        : StoppingStateStop
    75 -Description    : 停止动作得到停止状态
    76 -Input            : 
    77 -Output         : 
    78 -Return         : 
    79 * Modify Date      Version         Author           Modification
    80 * -----------------------------------------------
    81 * 2017/07/12      V1.0.0         Yu Weifeng       Created
    82 ******************************************************************************/
    83 void StoppingStateStop()
    84 {
    85     printf("Lift door stop!
    ");
    86 }
    StoppingState.c

    3)执行结果:

    book@book-desktop:/work/projects/test/DesignPatterns$ gcc -o StatePatternUsage RunningState.c

    StoppingState.c  OpenningState.c ClosingState.c StatePattern.c StatePatternUsage.c

    book@book-desktop:/work/projects/test/DesignPatterns$ ./StatePatternUsage

    Lift door open!

    Lift door close!

    Lift door run!

    Lift door stop!

    4)详细代码:

    https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/BehavioralDesignPatterns/StatePattern

    三、使用场景

    1.行为随状态的改变而改变的场景

    2.条件、分支判断语句的替代者

    四、优点

    1.结构清晰,将状态转移的逻辑从臃肿的switch语句中分散到了各个类中,避免了过多的switch...case等条件判断

    2.遵循设计原则,体现了开闭原则和单一职责原则

    3.封装性非常好

    五、缺点

    1.扩展会导致类膨胀,状态最好不要超过5个

  • 相关阅读:
    XVIII Open Cup named after E.V. Pankratiev Stage 5: Eastern Grand Prix
    XX Russia Team Open, High School Programming Contest St Petersburg, Barnaul, Tbilisi, Almaty, Kremenchug, November 30, 2019
    2019-2020 ICPC, NERC, Northern Eurasia Finals
    The 2019 China Collegiate Programming Contest Harbin Site
    Southeastern European Regional Programming Contest 2019
    2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)
    2019-2020 Saint-Petersburg Open High School Programming Contest (SpbKOSHP 19)
    hdu6354 Everything Has Changed (圆的相交弧长)
    hdu6341 Problem J. Let Sudoku Rotate (dfs)
    hdu6333 Problem B. Harvest of Apples(组合数+莫队)
  • 原文地址:https://www.cnblogs.com/yuweifeng/p/7157415.html
Copyright © 2011-2022 走看看