题目链接
Inaka composes music. Today’s arrangement includes a chord of nn notes that are pairwise distinct, represented by a permutation p 1 … n p_{1 \dots n} p1…n of integers from 1 to n (inclusive) denoting the notes from the lowest to the highest.
Her friend, Miyako, sneaks in and plays a trick by altering the chord with the following two operations:
Any number of consecutive Drop-2 operations is considered a multi-drop. Miyako would like to change the permutation to an ordered permutation, 1 , 2 , … , n 1, 2, \dots, n 1,2,…,n, in the fewest number of multi-drops possible. Please help her find the number of multi-drops needed.
The first line contains an integer n ( 2 ≤ n ≤ 500 ) n (2 \leq n \leq 500) n(2≤n≤500) — the number of notes.
The second line contains n space-separated integers p 1 , p 2 , … , p n p_1, p_2, \dots, p_n p1,p2,…,pn — the original permutation of notes.
The input guarantees each integer from 1 to n (inclusive) appears in the permutation exactly once.
Output one integer — the number of multi-drops required to change the permutation to an ordered one.
6
2 4 5 1 3 6
2
8
8 4 7 3 6 2 5 1
5
这题其实是非常简单的 d p dp dp,很多人容易被题目要求迷惑,我们试想,要求一个序列有序,很容易想到最长上升子序列,保持最长的子序列,调整其他位置即可,而我们看向 i n v e r t invert invert 操作,很明显提示你将序列看作一个环,而且细心一点就会发现,用 i n v e r t invert invert 搭配 d r o p drop drop 操作就可以将任意数字移到任意位置,那么题目到这里就很明确了,无非就是求一个环的最长上升子序列,剩下的元素个数就是需要操作的次数了,还有一个小细节,注意看题目数据大小,数据小一般就提示 DP 了,AC代码如下:
#include
using namespace std;
typedef long long ll;
const int N=505;
int n,a[N],dp[N];
int main(){
int n,ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++){
fill(dp,dp+n,1);
for(int j=0;j<n;j++){
for(int k=0;k<j;k++){
if(a[j]>a[k]) dp[j]=max(dp[j],dp[k]+1);
}
}
ans=max(ans,dp[n-1]);
rotate(a,a+1,a+n);
}
printf("%d",n-ans);
return 0;
}