
二. 思路
1. 搜索

2. 记忆化搜索

3. DP


三. 代码
1. 搜索
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
const int N=310, INF=2e9;
int n;
int s[N];//前缀和数组,快速区间求和
class Search
{
public:
Search()
{
initIO();
}
void initIO()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
}
//合并l到r石子的最小代价
int dfs(int l, int r)
{
if(l==r) return 0;//单石碓代价为0
//枚举l~r石子合并,从哪个分界点去合并
int cost=INF;
for(int k=l;k<r;++k)//k不能等于r,否则k+1有可能>r
cost=min(cost, dfs(l, k)+dfs(k+1, r));
return cost+s[r]-s[l-1];
}
}sh;
int main()
{
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>s[i];
s[i]+=s[i-1];
}
cout<<sh.dfs(1, n);
}
2. 记忆化搜索
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
const int N=310, INF=2e9;
int n;
int s[N];//前缀和数组,快速区间求和
class Search
{
public:
int f[N][N];//记忆化数组, 记录已经搜索过的状态
public:
Search()
{
initIO();
}
void init()
{
fill(f[0], f[0]+N*N, INF);
for(int i=1;i<=n;++i) f[i][i]=0;
}
void initIO()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
}
//合并l到r石子的最小代价
int dfs(int l, int r)
{//f[i][i]==0了,所以不用判断l==r时的情况
if(f[l][r]!=INF) return f[l][r];
//枚举l~r石子合并,从哪个分界点去合并
for(int k=l;k<r;++k)//k不能等于r,否则k+1有可能>r
f[l][r]=min(f[l][r], dfs(l, k)+dfs(k+1, r));
return f[l][r]+=s[r]-s[l-1];
}
}sh;
int main()
{
cin>>n;
sh.init();
for(int i=1;i<=n;++i)
{
cin>>s[i];
s[i]+=s[i-1];
}
cout<<sh.dfs(1, n);
}
3. DP
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
const int N=310, INF=2e9;
int n;
int s[N];//前缀和数组,快速区间求和
class DP
{
public:
int f[N][N];//f[i][j]表示区间i~j石子合并的代价
public:
DP()
{
initIO();
fill(f[0], f[0]+N*N, INF);
}
void initIO()
{
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
}
int work()
{
for(int len=1;len<=n;++len)//枚举区间长度,从小到大
for(int l=1;l+len-1<=n;++l)//枚举区间起点l, 同时保证r<=n
if(len==1) f[l][l]=0;//等同于初始化
else
{
int r=l+len-1;//算出区间右端点j
for(int k=l;k<r;++k)//枚举分界点k,注意k<j, 否则k+1可能>j
f[l][r]=min(f[l][r], f[l][k]+f[k+1][r]+s[r]-s[l-1]);
}
return f[1][n];
}
}dp;
int main()
{
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>s[i];
s[i]+=s[i-1];
}
cout<<dp.work();
}