
1 7 1 2 4 4 5 4 3
38
/*
题意:一个长度为n的数列,将其分成若干段(每一段的长度要<=20),
要求∑ai*(2^bi)最小,其中ai是每一段数列的第一项,bi是每一段的长度。
比如:n=7,A={1 2 4 4 5 4 3},将其分成1 2 4| 4 5| 4| 3,
则其所用空间为1*2^3+4*2^2+4*2^1+3*2^1=38,
而如果分成1 2| 4 4 5| 4 3,则其所用空间为1*2^2+4*2^3+4*2^2=52,比38大。
思路:区间dp
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)
#define bug printf("hihi\n")
#define eps 1e-8
typedef __int64 ll;
using namespace std;
#define INF 0x3f3f3f3f
#define N 65
ll dp[N];
ll a[N];
int n;
int main()
{
int i,j,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
memset(dp,INF,sizeof(dp));
for(i=n+1;i<=n+20;i++)
dp[i]=0;
dp[n]=a[n]*2;
for(i=n;i>=1;i--)
for(j=i+1;j<=min(i+20,n+1);j++)//在j这个位置分开
{
dp[i]=min(dp[i],a[i]*(1<<(j-i))+dp[j]);
}
printf("%I64d\n",dp[1]);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/u014737310/article/details/46827035