状态:f [ i ][ j ]表示前i个点换了j次的最小和
转移:用f [ i ][ j ]更新f [ i+1 ][ j+k-i-1](k为i后一点)
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,k,s;
int a[200];
int f[200][200*200];
int main()
{
scanf("%d %d %d",&n,&k,&s);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=i-1;j>=0;j--)
{
for(int k=0;k<=i*j;k++)//把i前j个点全部换入最左j个点最多需要i*j次
{
if(f[j][k]!=0x3f3f3f3f)
{
f[j+1][k+i-j-1]=min(f[j+1][k+i-j-1],f[j][k]+a[i]);
}
}
}
}
int ans=0x3f3f3f3f;
for(int i=0;i<=min(s,n*n);i++)
{
ans=min(ans,f[k][i]);
}
printf("%d\n",ans);
}