石子合併問題
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
在一個圓形操場的四周擺放着n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2 堆石子合併成新的一堆,並將新的一堆石子數記爲該次合併的得分。試設計一個算法,計算出將n堆石子合併成一堆的最小得分和最大得分。
對於給定n堆石子,計算合併成一堆的最小得分和最大得分。
Input
輸入數據的第1行是正整數n,1≤n≤100,表示有n堆石子。第二行有n個數,分別表示每堆石子的個數。
Output
輸出數據有兩行,第1行中的數是最小得分,第2行中的數是最大得分。
Sample Input
4 4 4 5 9
Sample Output
43 54
//////OJ提交runtime error了 暫時還不知道爲什麼,但是思路以及輸出結果目前沒問題
#include<iostream>
#include<vector>
#define inf 0x3f3f3f3f
using namespace std;
int min(int a, int b) {
return a < b ? a : b;
}
int main() {
int n;
int temp;
vector<int> a;
vector<int> b;
vector<int> c;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> temp;
a.push_back(temp);//求最小
c.push_back(temp);//備份求最大
}
int mincnt = 0;
if(n == 1){
mincnt = maxcnt = a[0];
}
while (a.size() > 1) {
for (int i = 0; i < a.size()-1; i++) {
b.push_back(a[i + 1] + a[i]);
}
b.push_back(a[a.size() - 1] + a[0]);
int min1 = inf;
int flag;
for (int i = 0; i < b.size(); i++) {
if (min1 > b[i]) {
min1 = b[i];
flag = i;
}
}
mincnt += min1;
if (flag == a.size()) {
a[0] = min1;
a.erase(a.begin() + (a.size() - 1));
}
else {
a[flag] = min1;
a.erase(a.begin() + flag + 1);
}
vector <int>().swap(b); //清空b中內容
}
int maxcnt = 0;
while (c.size() > 1) {
for (int i = 0; i < c.size() - 1; i++) {
b.push_back(c[i + 1] + c[i]);
}
b.push_back(c[c.size() - 1] + c[0]);
int max1 = 0;
int flag;
for (int i = 0; i < b.size(); i++) {
if (max1 < b[i]) {
max1 = b[i];
flag = i;
}
}
maxcnt += max1;
if (flag == c.size()) {
c[0] = max1;
c.erase(c.begin() + (c.size() - 1));
}
else {
c[flag] = max1;
c.erase(c.begin() + flag + 1);
}
vector <int>().swap(b);
}
cout << mincnt << endl;
cout << maxcnt << endl;
return 0;
}