可以把问题转化成区间来考虑。dp[i][j]表示从i到j所需吃掉的苹果。
这样状态方程就出来了dp[i][j]=min{dp[i][k-1]+dp[k+1][j]+(k+K)*(j-i+1)|i<=k<=j}。
边界条件为i==j时dp[i][j]=0;i==j-1时dp[i][j]=2*(i+K);i==j-2时,dp[i][j]=3*(i+K+1)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 510
int n,k;
int dp[M][M];
int vis[M][M];
int dfs(int l,int r)
{
if(vis[l][r]) return dp[l][r];
if(r==l) return dp[l][r]=0;
if(r==l+1) return dp[l][r]=2*(l+k);
if(r==l+2) return dp[l][r]=3*(l+k+1);
vis[l][r]=1;
int &ans=dp[l][r];
int len=r-l+1;
ans=(l+k)*len+dfs(l+1,r);
for(int i=l+1;i<r;i++)
ans=min(ans,(i+k)*len+dfs(l,i-1)+dfs(i+1,r));
ans=min(ans,(r+k)*len+dfs(l,r-1));
return ans;
}
int main()
{
freopen("in.txt","r",stdin);
int T,kase=1;
cin>>T;
while(T--)
{
cin>>n>>k;
memset(vis,0,sizeof(vis));
cout<<"Case "<<kase++<<": "<<dfs(1,n)<<endl;
}
return 0;
}