题意:n个人排成一排,每个人轮流上场,第i个人上场有(i-1)*a【i】的愤怒值,有一个小黑屋,你可以把人塞进去,先进的后出来,求最小的愤怒值。
dp不亏是dp真难(可能是我太菜了。。。感觉写了不少了但还是很难自己写出来,菜哭
题解;区间dp,断点k代表的是第i个人第几次出场。
dp【i】【j】=min(dp【i】【j】,dp【i+1】【i+k-1】+(k-1)*a【i】+dp【i+k】【j】+k*(b【j】-b【i+k-1】)
b数组是a的累加。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define ll long long
ll a[206],b[206],dp[206][206];
int main()
{
int t;
cin>>t;int o=0;
while(t--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=b[i-1]+a[i];
}
for(int i=0;i<=n+2;i++)
{
for(int j=i+1;j<=n+2;j++)
{
dp[i][j]=213456789;
if(i==j)
dp[i][j]=0;
}
}
for(int len=2;len<=n;len++)
{
for(int i=1;i+len-1<=n;i++)
{
int j=i+len-1;
for(int k=1;k<=j-i+1;k++)
{
dp[i][j] = min(dp[i][j], dp[i+1][i+k-1] + a[i] * (k-1) + dp[i+k][j] + k * (b[j] - b[i+k-1]));
}
}
}
printf("Case #%d: ",++o);
printf("%lld\n",dp[1][n]);
}
return 0;
}