问题描述:
在一个操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。规定每次至少选2 堆最多选k堆石子合并成新的一堆,合并的费用为新的一堆的石子数。试设计一个算法,计算出将n堆石子合并成一堆的最大总费用和最小总费用。
编程任务:
对于给定n堆石子,编程计算合并成一堆的最大总费用和最小总费用。
Input
测试数据的第1 行有2个正整数n和k,表示有n堆石子,每次至少选2堆最多选k堆石子合并。第2行有n个数,分别表示每堆石子的个数。
Output
输出最大总费用和最小总费用,用一空格隔开,每个答案一行。
Sample Input
7 3
45 13 12 16 9 5 22
Sample Output
593 199
#include<iostream> #include<algorithm> #include<vector> using namespace std; bool cmp ( int a, int b ) { return a>b; } void Insert ( vector<int> &f, int pos, int value ) { for ( int i = f.size() - 1; i > pos; i-- ) { f[i] = f[i - 1]; } f[pos] = value; } int Find ( vector<int> f, int value ) { int pos = f.size() - 1; while ( pos >= 0 && f[pos] < value ) { pos--; } return pos + 1; } int MaxNum ( vector<int> f ) { sort ( f.begin(), f.end() ); int Max; Max = 0; while ( f.size() >= 2 ) { int sum = f[f.size() - 1] + f[f.size() - 2]; Max = Max + sum; f.resize ( f.size() - 1 ); f[f.size() - 1] = sum; } return Max; } int MinNum ( vector<int> f, int len ) { sort ( f.begin(), f.end(), cmp ); int Min; Min = 0; while ( f.size() >= len ) { int sum = 0; for ( int i = f.size() - 1; i >= f.size() - len && i >= 0; i-- ) { sum = sum + f[i]; } Min = Min + sum; f.resize ( f.size() - len + 1 ); if ( f.size() > len ) { int pos = Find ( f, sum ); Insert ( f, pos, sum ); } else if ( f.size() != 1 ) { f[f.size() - 1] = sum; for ( int i = 0; i < f.size(); i++ ) { Min = Min + f[i]; } break; } else { break; } } return Min; } bool run() { int n, m; if ( ! ( cin >> n >> m ) ) return false; vector<int> f ( n ); for ( int i = 0; i < n; i++ ) { cin >> f[i]; } int Max, Min; Max = MaxNum ( f ); while ( f.size() % ( m - 1 ) != 1 ) { f.push_back ( 0 ); } Min = MinNum ( f, m ); cout << Max << " " << Min << endl; return true; } int main() { while ( run() ); return 0; }
初级程序员
by: Lyw 发表于:2019-09-24 11:37:21 顶(0) | 踩(0) 回复
好
回复评论