Blog of CodeJELLOW’S ENGINEERING NOTES
← 返回文章

石子合并

有N堆石子排成一排(n<=100),现要将石子有次序地合并成一堆,规定每次只能选相邻的两堆合并成一堆,并将新的一堆的石子数,记为该次合并的得分,编一程序,给出堆数n及每堆石子数(<=200);

本文目录 ⌄

    有N堆石子排成一排(n<=100),现要将石子有次序地合并成一堆,规定每次只能选相邻的两堆合并成一堆,并将新的一堆的石子数,记为该次合并的得分,编一程序,给出堆数n及每堆石子数(<=200);

    (1)选择一种合并石子的方案,使得做n-1次合并,得分的总和最少

    (2)选择一种合并石子的方案,使得做n-1次合并,得分的总和最多

    输入格式:

    第一行为石子堆数n

    第二行为每堆石子数,每两个数之间用一空格分隔。

    输出格式:

    第一行为最小合并得分,第二行是最大的合并得分。

    输入样例:

    在这里给出一组输入。例如:

    TEXT
    4
    4 5 9 4
    

    输出样例:

    在这里给出相应的输出。例如:

    TEXT
    44
    54

    题解

    TEXT
    
    #include <algorithm>
    #include <iostream>
    #include <vector>
    using namespace std;
    vector<int> vec(101);
    vector<vector<int>> dp_max(101, vector<int>(101, 0));
    vector<vector<int>> dp_min(101, vector<int>(101, 0));
    int max_num(int i, int j) {
      if (dp_max[i][j] ) {
        return dp_max[i][j];
      }
      if (i == j) {
        return 0;
      }
      int sum = 0, MAX = -1;
      for (int k = i; k <= j; k++) {
        sum += vec[k];
      }
      for (int k = i; k < j; k++) {
        MAX = max(max_num(i,k) + max_num(k+1,j) + sum, MAX);
      }
      dp_max[i][j]=MAX;
      return MAX;
    }
    int min_num(int i, int j) {
      if (dp_min[i][j]) {
        return dp_min[i][j];
      }
      if (i == j) {
        return 0;
      }
      int sum = 0, MIN =2010;
      for (int k = i; k <= j; k++) {
        sum += vec[k];
      }
      for (int k = i; k < j; k++) {
        MIN = min(min_num(i,k) + min_num(k+1,j) + sum, MIN);
      }
      dp_min[i][j]=MIN;
      return MIN;
    }
    int main() {
      int n;
      cin >> n;
      for (int i = 0; i < n; i++) {
        cin >> vec[i];
      }
      cout<< min_num(0,n-1)<<endl;
      cout << max_num(0, n-1) ;
      system("pause");
    }

    通过 RSS 订阅更新 →