翻看了很长题解
现在还是马马虎虎
有点看不懂
先收藏到博客
慢慢理解
区间dp
dp[i][j]表示从第i个人到第j个人的最小不高兴度,那么如果不管i前面的人,如果i是第k个登录舞台的人,那么i+1到i+k-1的人肯定已经登录上了舞台,那么枚举i是第k名登录舞台,这时候的dp方程就是
dp[i][j]=min(dp[i][j],dp[i][i+K-1]+dp[i+k][j]+a[i](k-1)+k((i+k~j)的不高兴度));
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[105];
int dp[105][105];
int sum[105];
int inf=999999;
int main()
{
int T;
scanf("%d",&T);
for(int e=1;e<=T;e++){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
memset(dp,0,sizeof dp);
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
dp[i][j]=inf;
}
}
for(int len=1;len<n;len++){
for(int i=1,j=i+len;i<=n&&j<=n;j++,i++){
for(int k=1;k<=len+1;k++){
dp[i][j]=min(dp[i][j],dp[i+1][i+k-1]+dp[i+k][j]+a[i]*(k-1)+k*(sum[j]-sum[i+k-1]));
}
}
}
printf("Case #%d: %d\n",e,dp[1][n]);
}
return 0;
}
下面是百度的记忆化搜索代码,还是记忆化搜索的代码容易理解,他们原理却相同
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int dp[110][110];
int arr[110],sum[110];
int n;
int solve(int i,int j)
{
int &ans=dp[i][j];
if(ans!=-1) return ans;
if(i>=j) return 0;
ans = INF ;
for(int k=1;k<=j-i+1;k++){
ans=min(ans,solve(i+1,i+k-1)+solve(i+k,j)+(k-1)*arr[i]+(sum[j]-sum[i+k-1])*k);
}
return ans;
}
int main()
{
int t,iCase=1;
cin>>t;
while(t--){
cin>>n;
sum[0]=0;
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
sum[i]=sum[i-1]+arr[i];
}
memset(dp,-1,sizeof dp);
printf("Case #%d: %d\n",iCase++,solve(1,n));
}
return 0;
}