题目大意: 值得注意的一点是题目要求的是这些子段之间的最大整数和。注意和Max Sum Plus Plus 这个题目的区别。
题解:
线性区间DP,对每一段考虑取或者不取。定义状态dp[i][j]指的是前i个数分为j段。
如果第j段不选的话dp[i][j]=dp[i-1][j],直接就是上一个状态的值。
如果选得话,dp[i][j]=dp[i-part[j]][j-1]+sum[i]-sum[i-part[j]]。前一共有i个数,第j段要占用i-part[j]个数,所以前j-1段要占用
i-part[j]个数。然后取最好的状态就行了。复杂度O(n*m)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=1000+7; ll dp[N][N]; ll arr[N]; ll part[N]; ll sum[N]; int main(){ ll n; while(cin>>n,n){ ll m; cin>>m; memset(dp,0,sizeof dp); memset(sum,0,sizeof sum); for(ll i=1;i<=m;i++) cin>>part[i]; for(ll i=1;i<=n;i++) cin>>arr[i]; for(ll i=1;i<=n;i++) sum[i]=sum[i-1]+arr[i]; for(ll i=1;i<=n;i++) for(ll j=1;j<=m;j++){ if(part[j]>i) dp[i][j]=dp[i-1][j]; else dp[i][j]=max(dp[i-1][j], dp[i-part[j]][j-1]+sum[i]-sum[i-part[j]]); } cout<<dp[n][m]<<endl; } return 0; }