题目大意:给你n个数字,给你k次两两交换数字的机会
问你前m个数字的和最小可能是多少?
思路:dp
首先f[i][j]表示前i个数有j次交换的和
a[i]表示第n个数字的值
我们可以利用一个变量k表示第k个数
这样就可以利用k-i-1表示两两交换位置
注意i要从k-1开始到0,不然会有后效性
那么可以写出式子f[i+1][j+k-i-1]=min(f[i][j+k-i-1],f[i][j]+a[k])
具体参照代码注释
AC代码:

#include <iostream>
#include <string.h>
using namespace std;
int a[155];
int f[155][155*155];
int main()
{
    int n,m,k;
    memset(f,0x3f3f3f,sizeof(f));
    int ans=1010010100;//因为最多就150个一百万的数据,int就够了
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)cin>>a[i];
    f[0][0]=0;
    for(int k=1;k<=n;k++){
        for(int i=k-1;i>=0;i--){//从k-1开始是为了防止后效性
        //不然f[i][j]变动之后之后的f[i+1][j]会受新的f[i][j]的影响
            for(int j=0;j<=k*i;j++){
                  f[i+1][j+k-i-1]=min(f[i+1][j+k-i-1],f[i][j]+a[k]);
          //k-i-1表示移动距离
            }
        }
    }
    for(int j=0;j<=min((n*(n)),k);j++){//最多移动题目要求的k次或者n*n次
        ans=min(f[m][j],ans);
    }
    cout<<ans<<endl;
    return 0;
}