1. 程式人生 > 實用技巧 >2020牛客多校第五場D題Drop Voicing(思維 dp lis)

2020牛客多校第五場D題Drop Voicing(思維 dp lis)

題目連結:https://ac.nowcoder.com/acm/contest/5670/D

題意:輸入一個n個數的序列,你有兩種操作,第一種把陣列第一個移到最後一個,第二種把陣列的倒數第二個移到第一個,連續第二種操作為一次花費(一次花費無論多少次),輸出最少費用使序列變為升序,即為[1,2,3,4,5.....n]

題解:第一種操作並不能更換數字之間的順序,無論怎麼樣置換,都可以把他看做成一個環。第二種操作我們就可以把一個數字移動,結合第一種操作可以移動到他原來的位置。這樣我們就求要移動多少個數字就可以了,移動多少個數字變成升序?那不就是lis,列舉n次第一種操作後的陣列,每次計算lis,ans=n-lis;

這裡第一種操作,我們用STL種的rotate

rotate(beg,newBeg,end)
將區間[beg,end)內的元素進行旋轉,執行後*newBeg成為新的第一元素;

#include <bits/stdc++.h>
using namespace std;
const int maxn=500+7;
typedef long long ll;
int a[maxn];
int dp[maxn];
int lis(int n){
    int res = 0;
    for(int i = 0; i < n; i ++){
        dp[i] = 1;
        
for(int j = 0; j < i; j ++){ if(a[j] < a[i]){ dp[i] = max(dp[i], dp[j] + 1); } } res = max(res, dp[i]); } return res; } int main(){ int t,n; scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); }
int ans=0; for(int i=0;i<n;i++){ ans=max(ans,lis(n)); rotate(a,a+1,a+n); } printf("%d\n",n-ans); return 0; }