题目 给定一个长度为
n
(
2
≤
n
≤
500
)
n(2≤n≤500)
n(2≤n≤500)的排列
a
[
0...
n
−
1
]
a[0...n-1]
a[0...n−1],有两种操作: 1、drop-2:将倒数第二个数移到最前面 2、invert:将第一个数移到最后面 且连续的drop-2操作称为multi-drop,问最少需要多少个multi-drop操作,使得此排列为升序(即最终的排列为1,2,…,n)
思路 称连续的invert操作为multi-invert,可以发现将一个数移到任一位置需要最多1个multi-drop操作和多个multi-invert操作。 如
x
1
x
2
x
3
x
4
x
5
x
6
x
7
x_1x_2x_3x_4x_5x_6x_7
x1x2x3x4x5x6x7,现在要把
x
4
x_4
x4移到
x
5
x_5
x5和
x
6
x_6
x6之间 (1)将
x
1
x_1
x1~
x
5
x_5
x5移到后面:
x
6
x
7
x
1
x
2
x
3
x
4
x
5
x_6x_7x_1x_2x_3x_4x_5
x6x7x1x2x3x4x5,1次multi-invert (2)将
x
6
x_6
x6~
x
3
x_3
x3移到后面:
x
4
x
5
x
6
x
7
x
1
x
2
x
3
x_4x_5x_6x_7x_1x_2x_3
x4x5x6x7x1x2x3,1次multi-invert (3)将
x
6
x_6
x6~
x
2
x_2
x2移到前面:
x
6
x
7
x
1
x
2
x
4
x
5
x
3
x_6x_7x_1x_2x_4x_5x_3
x6x7x1x2x4x5x3,1次multi-drop (4)将
x
6
x_6
x6~
x
7
x_7
x7移到后面:
x
1
x
2
x
4
x
5
x
3
x
6
x
7
x_1x_2x_4x_5x_3x_6x_7
x1x2x4x5x3x6x7,1次multi-invert 考虑排列的LIS,对于不属于LIS的数字,最多使用一次multi-drop,将其移到合适的位置,使得len(LIS)+1,那么答案就是n-len(LIS)。 由于multi-invert操作的次数不计入答案,每次将原排列的前i个(0≤i≤n-1)个数移到后面,得到n个排列,对于每个排列求LIS,最终的ans=min{n-len(LIS)};
ac代码
#include<bits/stdc++.h>usingnamespace std;constint maxn =5e2+10;int n;int dp[maxn];int a[maxn], b[maxn];intmain(){//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);scanf("%d",&n);for(int i =0; i < n; i++)scanf("%d",&a[i]);int ans = INT_MAX;for(int k =0; k < n; k++){for(int i =0; i < n; i++) b[(i+n-1-k+n)%n]= a[i];
dp[0]=1;for(int i =1; i < n; i++){
dp[i]=1;for(int j =0; j < i; j++)if(b[i]>b[j]) dp[i]=max(dp[i], dp[j]+1);}int lis =1;for(int i =0; i < n; i++) lis =max(lis, dp[i]);
ans =min(ans, n-lis);}printf("%d\n", ans);return0;}