• E - Swap


    E - Swap Editorial


    Time Limit: 2 sec / Memory Limit: 1024 MB

    Score : 500500 points

    Problem Statement

    Given is a string SS consisting of KEY.

    How many strings are there that can be obtained with at most KK swaps of two adjacent characters in SS?

    Constraints

    • 2 \leq |S| \leq 302≤∣S∣≤30
    • 0 \leq K \leq 10^90≤K≤109
    • SS consists of KEY.

    Input

    Input is given from Standard Input in the following format:

    SS
    KK
    

    Output

    Print the answer.


    Sample Input 1 Copy

    Copy

    KEY
    1
    

    Sample Output 1 Copy

    Copy

    3
    

    With at most one swap, there are three strings that can be obtained: KEYEKYKYE.


    Sample Input 2 Copy

    Copy

    KKEE
    2
    

    Sample Output 2 Copy

    Copy

    4
    

    With at most two swaps, there are four strings that can be obtained: KKEEKEKEEKKEKEEK.


    Sample Input 3 Copy

    Copy

    KKEEYY
    1000000000
    

    Sample Output 3 Copy

    Copy

    90

     =========================================================================

    此类题也只能说很难去证明为什么这样做不会缺失或者重复

    EYEK

    一维代表位置,二维代表e的个数,三维代表y的个数,四维代表交换次数

    而按照正确方法我们得到的是如下结果

    dp[1][1][0][0]=1

    dp[1][1][0][1]=0

    dp[1][1][0][2]=0

    dp[1][1][0][3]=0

    也就是交换两次结果也是0,可是如果我们把第二个e交换到第一个位置也是一种方法,而本题正确做法确实找到离当前e最近的那一个e进行转移。这就很让人不解

    EYE为例

    dp[2][2][0][0]为 1,显然不正确

    但其转移到 dp[3][2][1][1]的时候,Y遍历E,会遇见一个比它大的E,也就把次数给加了上去。所以我们这样做是正确的。在累积多个相同字母时,如果我们没遇见其它字母,那么答案就一直是1种,(即先不计算与不同字母的交换),直到我们把不同字母提到前面,才产生了步数的变化和方案的累加。而且这么多不合理的1并不会影响答案,因为交换次数是0,我们最终获取答案的时候,仅仅取dp[n]的。

    1. # include
    2. # include
    3. # include
    4. # include
    5. # include
    6. # include
    7. # include
    8. # include
    9. # include
    10. # include
    11. using namespace std;
    12. typedef long long int ll;
    13. const int N=32;
    14. const int C=N*(N-1)/2;
    15. string s;
    16. int K;
    17. ll dp[N][N][N][C];
    18. vector<int>kp,ep,yp;
    19. int main()
    20. {
    21. cin>>s>>K;
    22. s=" "+s;
    23. int n=s.size()-1;
    24. K=min(K,n*(n-1)/2);
    25. for(int i=1; i<=n; i++)
    26. {
    27. if(s[i]=='K')
    28. {
    29. kp.push_back(i);
    30. }
    31. else if(s[i]=='E')
    32. {
    33. ep.push_back(i);
    34. }
    35. else if(s[i]=='Y')
    36. {
    37. yp.push_back(i);
    38. }
    39. }
    40. int ck=kp.size();
    41. int ce=ep.size();
    42. int cy=yp.size();
    43. dp[0][0][0][0]=1;
    44. for(int i=0; i
    45. {
    46. for(int e=0; e<=ce; e++)
    47. {
    48. for(int y=0; y<=cy; y++)
    49. {
    50. int kk=i-e-y;
    51. if(kk<0||kk>ck)
    52. continue;
    53. for(int st=0; st<=K; st++)
    54. {
    55. if(!dp[i][e][y][st])
    56. continue;
    57. if (kk < ck)
    58. {
    59. int moveSteps = 0; // 把i+1位置的K往左交换
    60. for (int l = 0; l < e; l++) if (ep[l] > kp[kk]) moveSteps++;
    61. for (int l = 0; l < y; l++) if (yp[l] > kp[kk]) moveSteps++;
    62. if (st + moveSteps <= K) dp[i + 1][e][y][st + moveSteps] += dp[i][e][y][st];
    63. }
    64. if (e < ce)
    65. {
    66. int moveSteps = 0;
    67. for (int l = 0; l < kk; l++) if (kp[l] > ep[e]) moveSteps++;
    68. for (int l = 0; l < y; l++) if (yp[l] > ep[e]) moveSteps++;
    69. if (st + moveSteps <= K) dp[i + 1][e + 1][y][st+ moveSteps] += dp[i][e][y][st];
    70. }
    71. if (y < cy)
    72. {
    73. int moveSteps = 0;
    74. for (int l = 0; l < kk; l++) if (kp[l] > yp[y]) moveSteps++;
    75. for (int l = 0; l < e; l++) if (ep[l] > yp[y]) moveSteps++;
    76. if (st+ moveSteps <= K) dp[i + 1][e][y + 1][st+ moveSteps] += dp[i][e][y][st];
    77. }
    78. }
    79. }
    80. }
    81. }
    82. // EKEY
    83. // cout<
    84. ll res = 0;
    85. for (int i = 0; i <= K; i++) res+= dp[n][ce][cy][i];
    86. cout << res << endl;
    87. return 0;
    88. }

  • 相关阅读:
    基于java+ssm的在线投票管理系统-计算机毕业设计
    慧销平台ThreadPoolExecutor内存泄漏分析
    发布 jar 包到 maven 中央仓库
    vue表单及修饰符,vue事件,方法
    docker(五)构建私有仓库
    递归实现指数型枚举
    如何在 R 中使用 Fisher 的最小显着性差异 (LSD)
    自建Web视频会议,视频互动,SFU/MCU融合架构选型方案分析
    什么是软件EV代码签名证书
    Linux C 应用编程学习笔记——(2)文件 I/O 基础
  • 原文地址:https://blog.csdn.net/jisuanji2606414/article/details/126119096