题意很绕啊
有一群要上场的屌丝,每个人有个值d,如果他第k个上场,那他不开心的值就是(k-1)*d
现在有个小黑屋= =(一个栈),轮到某个人的时候,有两个选择,把他丢进小黑屋,或者让他直接上场。
dp[i][j]表示这段区间的最小值。这里的意思是把每个区间当做一个子问题,也就是相当于区间(1,j-i+1)。
枚举区间第一个人的上场时间。
如果在第m个上场,那么m个往后的人就要用dp[m+1][j]+sum[m+1...j]*(m-i+1)
预处理一下前缀和
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <iostream>
using namespace std;
const int MAXN =310;
const int INF =1000000007 ;
const int MOD =1000000007;
const double EPS=1e-8;
const double pi = acos(-1);
int dp[MAXN][MAXN];
int a[MAXN];
int sum[MAXN];
int main(){
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++){
int n;
scanf("%d",&n);
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++){
scanf("%d",a+i);
sum[i]=sum[i-1]+a[i];
}
memset(dp,0,sizeof(dp));
for(int k=0;k<n;k++){
for(int i=1;i+k<=n;i++){
int j=i+k;
dp[i][j]=INF;
for(int m=i;m<=j;m++){
int temp=m-i+1;
dp[i][j]=min(dp[i][j],dp[i+1][m]+a[i]*(temp-1)+dp[m+1][j]+(sum[j]-sum[m])*temp);
}
}
}
printf("Case #%d: ",cas);
printf("%d\n",dp[1][n]);
}
}