洛谷P3847 [TJOI2007]調整隊形
阿新 • • 發佈:2017-09-09
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]調整隊形