题目
题解
思路
搜索。对于任何一个区间[l,r],枚举其中的每一个点i,将 l~ i-1看为左子树,i+1 ~ r 看为右子树,再递归找最小的即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define db double
#define ll long long
int n;
db k,c,sum=0;
db a[35];
db dp[105][105][105];
const db INF=100000086;
db DFS(int l,int r,int h){
if(dp[l][r][h]!=INF) return dp[l][r][h];
for(int i=l;i<=r;i++){
db now=a[i]*(k*h+c);
if(l<=i-1)
now+=DFS(l,i-1,h+1);
if(r>=i+1)
now+=DFS(i+1,r,h+1);
dp[l][r][h]=min(dp[l][r][h],now);
}
return dp[l][r][h];
}
int main(){
scanf("%d%lf%lf",&n,&k,&c);
for(int i=1;i<=n;i++){
scanf("%lf",&a[i]);
sum+=a[i];
}
for(int i=1;i<=n;i++){
a[i]/=sum;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
dp[i][j][k]=INF;
printf("%.3lf",DFS(1,n,1));
return 0;
}