dp[i][j]表示i为最后一个分段的结尾,一共分了j端。
详细的解释可以看这篇博客,想到预处理正序对就很简单了。
http://blog.csdn.net/wty__/article/details/38234127
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
using namespace std;
const int MAXN=1010;
const int MAXK=55;
const int INF=1e9+7;
int n,s,k;
int dp[MAXN];
int a[MAXN];
int num[MAXN][MAXN]={0};
int main(){
freopen("flight.in","r",stdin);
freopen("flight.out","w",stdout);
fill(dp,dp+MAXN,INF);
scanf("%d%d%d",&n,&s,&k);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[j]<a[i]){
num[a[j]][a[i]]++;
}
}
}
for(int i=1;i<=s;i++){
for(int j=1;j<=s;j++){
num[i][j]=num[i-1][j]+num[i][j-1]-num[i-1][j-1]+num[i][j];
}
}
dp[0]=0;
for(int i=1;i<=k;i++){
for(int t=s;t>=0;t--){
for(int j=s;t<j;j--){
dp[j]=min(dp[j],dp[t]+num[j][j]-num[t][j]-num[j][t]+num[t][t]);
}
}
}
printf("%d\n",dp[s]);
}