题目来源:https://ac.nowcoder.com/acm/contest/5670#submit/%7B%22problemIdFilter%22%3A209988%2C%22statusTypeFilter%22%3A5%7D
题意:
给你一个p的全排列,有两种操作:
选择倒数第二个挪到第一个
把第一个挪到最后一个
如果是连续的第一种操作,则只花费1,第二种操作不花费。
问最少的花费使得p的全排列变成一个顺序的排列。

题目思路:
最少花费,分析了一下,要了解这个两个操作的本质,其实画了一下发现,实际是把最后一个数挪到前面任意两个数之间,那么思路就是:因为任意一个数花费为0可以成为最后一个,而最后一个数花费为1就可以挪到任意两个数之间,我们要求这个是一个升序,所以先找到最长的升子序列,剩下的数就是结果,相减。
算法:dp,规律

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll
#define N 1010
int a[N*2],dp[N],n,b[N];

int solve()
{
    for (int i = 1;i <= n;i++)  
    dp[i] = inf;
    for (int i = 1;i <= n;i++) 
    *lower_bound(dp +1 , dp + n + 1, a[i]) = a[i];
    return lower_bound(dp + 1, dp + n + 1, inf) - dp - 1;
}

int main() {
    cin>>n;
    for (int i = 1; i <= n; i++) 
    cin>>a[i];
    for (int i = 1; i <= n; i++) 
    a[i + n] = a[i];
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        ans = max(ans, solve());
        for(int j = 1; j <n+1; j++){
            b[j] = a[j];
        }
        for(int j = 1; j < n+1; j++)
    {
            a[j] = b[j + 1];
        }
        a[n] = b[1];
    }
    cout<<n-ans<<endl;
    return 0;
}