1. 程式人生 > >洛谷P3847 [TJOI2007]調整隊形

洛谷P3847 [TJOI2007]調整隊形

blog 一個數 data name namespace efi ostream col clas

P3847 [TJOI2007]調整隊形

題目背景

學校藝術節上,規定合唱隊要參加比賽,各個隊員的衣服顏色不能很混亂:合唱隊員應排成一橫排,且衣服顏色必須是左右對稱的。

例如:“紅藍綠藍紅”或“紅藍綠綠藍紅”都是符合的,而“紅藍綠紅”或“藍綠藍紅”就不符合要求。

合唱隊人數自然很多,僅現有的同學就可能會有3000個。老師希望將合唱隊調整得符合要求,但想要調整盡量少,減少麻煩。以下任一動作認為是一次調整:

題目描述

1、在隊伍左或右邊加一個人(衣服顏色依要求而定);

2、在隊伍中任兩個人中間插入一個人(衣服顏色依要求而定);

3、剔掉一個人;

4、讓一個人換衣服顏色;

老師想知道就目前的隊形最少的調整次數是多少,請你編一個程序來回答他。

因為加入合唱隊很熱門,你可以認為人數是無限的,即隨時想加一個人都能找到人。同時衣服顏色也是任意的。

輸入輸出格式

輸入格式:

第一行是一個整數n(1<=n<=3000)。

第二行是n個整數,從左到右分別表示現有的每個隊員衣服的顏色號,都是1到3000的整數。

輸出格式:

一個數,即對於輸入隊列,要調整得符合要求,最少的調整次數。

輸入輸出樣例

輸入樣例#1:
5
1 2 2 4 3
輸出樣例#1:
2
/*
    操作一共有四種,但是我們本著簡化的原則可以發現 操作1,2 即往數列裏加數可以等效的被一步操作3 即刪掉 你想加數對應的那個數來代替,所以無非就兩種操作:1.改變一個數。2.刪掉一個數。求最少經過幾步操作可以使原數列變為回文的 
    我們考慮dp[i][j]表示把i…j變成回文所需的最小步數,則如果 
    a[i]==a[j] 則dp[i][j]=dp[i+1][j-1] 
    else 
    dp[i][j]=dp[i+1][j-1]+1 改變一個數 
    dp[i][j]=dp[i+1][j]+1 刪掉a[i] 
    dp[i][j]=dp[i][j-1]+1 刪掉a[j] 
    取最小值即可。復雜度O(n2)
*/ #include<iostream> #include<cstdio> using namespace std; #define maxn 3010 int dp[maxn][maxn],n,a[maxn]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int len=2;len<=n;len++){ for(int i=1;i+len-1<=n;i++){
int j=i+len-1; if(a[i]==a[j])dp[i][j]=dp[i+1][j-1]; else dp[i][j]=min(min(dp[i+1][j-1],dp[i+1][j]),dp[i][j-1])+1; } } printf("%d",dp[1][n]); }

洛谷P3847 [TJOI2007]調整隊形