Solution
f[i][j]
f
[
i
]
[
j
]
表示前
i
i
天经历出逃了 次,且第
i+1
i
+
1
天进行了出逃
f[i][j]=min(f[k][j−1]+count(k+1,i))
f
[
i
]
[
j
]
=
m
i
n
(
f
[
k
]
[
j
−
1
]
+
c
o
u
n
t
(
k
+
1
,
i
)
)
其中
count(x,y)
c
o
u
n
t
(
x
,
y
)
表示
ax⋯ay
a
x
⋯
a
y
和
1,2⋯y−x+1
1
,
2
⋯
y
−
x
+
1
的差别数
这样我们可以得到
n4
n
4
的暴力
但是我们可以预处理出来这个
count
c
o
u
n
t
用
cnt[i][j]
c
n
t
[
i
]
[
j
]
表示
ai⋯aj
a
i
⋯
a
j
和
0,1⋯j−i
0
,
1
⋯
j
−
i
然后就可以得到一个
n3
n
3
的dp
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1010
#define inf 0x3f3f3f3f
int n,a[N],cnt[N][N],f[N][N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
//i-j与0..j-i
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
for(int k=0;k<=j-i;k++){
cnt[i][j]+=(a[i+k]!=k);
}
}
}
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=0;k<i;k++){
if(f[k][j-1]==inf) continue;
f[i][j]=min(f[i][j],f[k][j-1]+cnt[k+1][i]);
}
}
}
for(int i=1;i<=n;i++) printf("%d\n",f[n][i]);
return 0;
}