Pagini recente » Cod sursa (job #1504872) | Cod sursa (job #1877162) | Cod sursa (job #1724613) | Cod sursa (job #1025087) | Cod sursa (job #2421138)
// http://www.cs.ust.hk/mjg_lib/bibs/DPSu/DPSu.Files/0603055.pdf
#include <fstream>
#include <algorithm>
#include <stack>
#include <map>
using namespace std;
ifstream in("podm.in");
ofstream out("podm.out");
const int N_MAX = 500;
int N, nrBridges = -1;
pair<int, int> Bridges[2 * N_MAX], w[N_MAX + 2];
map<pair<int, int>, int> Childs;
long long M[2 * N_MAX][N_MAX + 1];
void Mark_Bridges() {
rotate(w, min_element(w, w + N), w + N); //aducem cel mai mic numar pe primul loc
for (int i = 0; i < N; ++i)
w[i].second = i;
w[N] = w[0];
stack<int> S; //stiva in care retinem indici
for(int i = 1; i <= N; ++i) { //parcurgem in sens invers trigonometric
S.push(i - 1);
while (w[i] < w[S.top()]) {
int t = S.top();
S.pop();
Bridges[++nrBridges].first = S.top(), Bridges[nrBridges].second = t;
Bridges[++nrBridges].first = t, Bridges[nrBridges].second = (i == N ? 0 : i);
Childs[make_pair(S.top(), (i == N ? 0 : i))] = nrBridges; //este minson, iar nrBridges - 1 este maxson
}
}
}
long long Partition() {
for (int ind = 0; ind <= nrBridges; ++ind) {
int i = Bridges[ind].first, j = Bridges[ind].second;
if (w[i] > w[j]) swap(i, j);
if (!Childs.count(Bridges[ind])) {//frunza
M[ind][i] = 0;
for (int k = 0; k < N; ++k) //parcurgem toate conurile formate cu frunza (i, j)
if (w[k] < w[i])
M[ind][k] = 1LL * w[i].first * w[j].first * w[k].first;
}
else {
int s = Childs[Bridges[ind]];
M[ind][i] = M[s][i] + M[s - 1][i];
for (int k = 0; k < N; ++k) //parcurgem toate conurile formate puntea (i, j)
if (w[k] < w[i])
M[ind][k] = min(M[ind][i] + 1LL * w[i].first * w[j].first * w[k].first, M[s][k] + M[s - 1][k]);
}
}
return M[Childs[make_pair(0, 0)]][0] + M[Childs[make_pair(0, 0)] - 1][0];
}
int main() {
in >> N;
++N;
for (int i = 0; i < N; ++i)
in >> w[i].first;
Mark_Bridges();
out << Partition();
return 0;
}