題意: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;
}