问题:一个操场的四周摆放着n堆石子,每次把两个相邻的两堆石子合并起来,最后合并成一堆,每次搬动就要花费力气,力气的代价是两堆石子的数量之和,问:如何使总的花费的力气最小。(并非贪心)
方法:动态规划
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
vector<vector<int>>m;
int digui(int i, int j, vector<int>& arr)
{
if (m[i][j] != 0)
return m[i][j];
if (i == j)
{
m[i][j] = arr[i];
return arr[i];
}
if (i == j - 1)
{
m[i][j] = arr[i] + arr[j];
return arr[i] + arr[j];
}
int temp = INT_MAX;
for (int k = i; k < j; k++)
temp = min(digui(i, k, arr) + digui(k + 1, j, arr), temp);
m[i][j] = temp;
return m[i][j];
}
int dp_1(int n,vector<int>&arr)
{
vector<vector<int>>dp(n + 1, vector<int>(n + 1, 0));
for (int i = 1; i <=n; i++)
{
dp[i][i] = arr[i];
if(i<n)
dp[i][i + 1] = arr[i] + arr[i + 1];
}
for (int i = n-1; i>=1; i--)
{
for (int j = i+1; j <= n; j++)
{
int temp = INT_MAX;
for (int k = i; k < j; k++)
temp = min(temp, dp[i][k] + dp[k + 1][j]);
dp[i][j] = temp;
}
}
return dp[1][n];
}
int main()
{
int n;
while (cin >> n)
{
//m = vector<vector<int>>(n + 1, vector<int>(n + 1, 0));
vector<int>v;
v.push_back(0);
int num = 0;
for (int i = 1; i <= n; i++)
{
cin >> num;
v.push_back(num);
}
//cout << digui(1, n, v);
cout << dp_1(n, v);
}
return 0;
}
/*
7
1 5 7 2 6 9 4
*/