• GarsiaWachs算法


     这个算法可以用来解决石子合并问题(大数据版)。

    洛谷有题:P5569 [SDOI2008]石子合并

    对于一堆石子(链式):

      1.  从最左边开始向右走直到 stone[ k ] <= stone[ k + 2 ]  然后合并 stone[ k + 1 ] += stone[ k ];

      2.  从k 往前走 直到 stone[ j ] > stone[ k  ] + stone[ k + 1 ] 然后将新合并的数放在 j 后面  

          如果不存在这样的 j ,就放在最前面

      3.  如果我们找不到这样的 k , 就合并最后的两个数即 stone[ n ] 和 stone[ n - 1 ] (显然这两个数是最小的)

      4.  重复第一步。

    代码如下:

     1 /*
     2 2019-10-30
     3 P5569 [SDOI2008]石子合并
     4 czq
     5 */
     6 
     7 #include <cstdio>
     8 #include <iostream>
     9 #include <algorithm>
    10 using namespace std;
    11 const int N = 4e4 + 10;
    12 
    13 int n;
    14 int stone[N];
    15 
    16 int main()
    17 {
    18     cin >> n;
    19     for(int i = 1; i <= n; i++) scanf("%d", &stone[i]);
    20 
    21     //left 代表最左边的下标, ans 记录答案
    22     int ans = 0, left = 1;
    23 
    24     //当至少存在三堆石子时, 即 left n-1 n 
    25     while(left < n - 1)
    26     {
    27         int k;
    28         for(k = left; k < n - 1; k++)
    29         {
    30             if(stone[k] <= stone[k+2])
    31             {
    32                 stone[k+1] += stone[k]; //合并
    33                 ans += stone[k+1];      //加到答案里
    34                 // k 左边的往右移一位 将 k 覆盖掉
    35                 for(int j = k; j > left; j--)   stone[j] = stone[j - 1];
    36                 left ++;    //由于移位所以最左边要加 1
    37 
    38                 //向左查找 也就是第二步
    39                 int j = k + 1;
    40                 while(stone[j] > stone[j-1] && j > left)
    41                 {
    42                     //交换,将新合并石子的前移
    43                     swap(stone[j], stone[j-1]);
    44                     j --;
    45                 }
    46                 break;
    47             }
    48         }
    49         //不存在这样的 k
    50         if(k == n - 1)
    51         {
    52             //将最右边的石子加到倒数第二堆,
    53             stone[n - 1] += stone[n];
    54             //加上目前最右边的石子, 最右边的石子已经不存在了 所以 --n
    55             ans += stone[--n];
    56         }
    57     }
    58 
    59     //加上还剩下的两堆石子
    60     ans += stone[n] + stone[n-1];
    61 
    62     cout << ans << endl;
    63 
    64     return 0;
    65 }

      如果看不懂代码看例子

      接下来举个例子:假设有 6 堆石子:  left = 1  n = 6  ans = 0  d 为新合并的数

     

    代码运行截图:

      

      随机举的例子,不是很好,可以自己在理解一下

  • 相关阅读:
    flutter 日常所记
    flutter 项目打包出错问题
    flutter去除白屏,添加启动图
    flutter快捷键总结
    flutter组件总结
    首次使用flutter
    微信小程序引入坐标反解析
    公众号H5引入微信地图组件的正确姿势
    小程序获取unionid的方法
    对比两个文件夹或者文件的差异
  • 原文地址:https://www.cnblogs.com/nonameless/p/11768957.html
Copyright © 2020-2023  润新知