题目链接:Wall Street Monopoly
这题读题都读了一半天,mmp…(英文果然差)。
看到这一题,我就立马联想到石子合并这一经典问题了,事实也确实如此,类似矩阵连乘,寻求最优分割点。
0 i = j (无需合并)
dp[i][j] = { min(dp[i][j], dp[i][k] + dp[k + 1][j] + expense(i, k, j) i < j
无非再在求解合并时寻找最小代价即可。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n, m, ans = 1;
struct node {
int x, y;
}a[1024];
long long dp[1024][1024];
long long Expen(int left, int mid, int right)
{
long long exp;
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
for(int i = left; i <= mid; ++i) {
x1 += a[i].x; // 累加
y1 = max(y1, a[i].y); //求解最大
}
for(int i = mid + 1; i <= right; ++i) {
x2 += a[i].x;
y2 = max(y2, a[i].y);
}
exp = min((long long)x1 * y2, (long long)x2 * y1);
exp = min(exp, (long long)x1 * x2);
exp = min(exp, (long long)y1 * y2);
return exp * 100;
}
void WorkPro()
{
long long exp;
for(int k = 1; k < m; ++k) {
for(int i = 1; i + k <= m; ++i) { //i ~ i + k
exp = Expen(i, i, i + k);
dp[i][i + k] = dp[i][i] + dp[i + 1][i + k] + exp; // 小 --> 大
for(int j = i + 1; j < i + k; ++j) { // 切割点
dp[i][i + k] = min(dp[i][i + k], dp[i][j] + dp[j + 1][i + k] + Expen(i, j, i + k));
}
}
}
}
int main()
{
cin >> n;
while(n--) {
cin >> m;
for(int i = 0; i < 1024; ++i)
for(int j = 0; j < 1024; ++j)
dp[i][j] = 0; // Clear
for(int i = 1; i <= m; ++i) cin >> a[i].x >> a[i].y;
WorkPro();
cout << "The minimum cost for lot #" << ans << " is $" << dp[1][m] << "." << endl;
cout << endl;
ans++;
}
return 0;
}