点击打开链接
题意难度太高,后来问llm说大致是 给你n个数,然后让你随意划分成任意段区间(每一段最长为20),保证最后的区间和最小,
每一段区间值的算法是这样的,该区间值等于区间首字母*2^(区间长度);
题解:区间dp,
初始化: 长度最长为20,那么当 l<20时, dp[i][j]=a[i]*pow(2,l)*2;
when i>20: dp[i][j]=(sum[j]-sum[i-1])*2; 所有数字都是单个区间,没有合并。
之后遍历每个区间即可。
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=105; ll n,m,p,h,c; ll a[maxn],sum[maxn]; ll dp[maxn][maxn]; ll Pow(int x){ ll ret=1; for(int i=1;i<=x;++i) ret*=2; return ret; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%lld",&n); for(int i=1;i<=n;++i){ scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i]; } for(int l=0;l<=n;++l){ for(int i=1;i+l<=n;++i){ int j=i+l; if(l<20) dp[i][j]=a[i]*Pow(l); else dp[i][j]=sum[j]-sum[i-1]; for(int k=i;k<=j;++k){ dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); } } } printf("%lld\n",dp[1][n]*2); } return 0; }