【tju】【dp】调整队形
问题描述
学校艺术节上,规定合唱队要参加比赛,各个队员的衣服颜色不能很混乱:合唱队员应排成一横排,且衣服颜色必须是左右对称的。
例如:“红蓝绿蓝红”或“红蓝绿绿蓝红”都是符合的,而“红蓝绿红”或“蓝绿蓝红”就不符合要求。
合唱队人数自然很多,仅现有的同学就可能会有3000个。老师希望将合唱队调整得符合要求,但想要调整尽量少,减少麻烦。以下任一动作认为是一次调整:
1、在队伍左或右边加一个人(衣服颜色依要求而定);
2、在队伍中任两个人中间插入一个人(衣服颜色依要求而定);
3、剔掉一个人;
4、让一个人换衣服颜色;
老师想知道就目前的队形最少的调整次数是多少,请你编一个程序来回答他。
因为加入合唱队很热门,你可以认为人数是无限的,即随时想加一个人都能找到人。同时衣服颜色也是任意的。
输入文件
第一行是一个整数n(1≤n≤3000)。
第二行是n个整数,从左到右分别表示现有的每个队员衣服的颜色号,都是1到3000的整数。
输出文件
一个数,即对于输入队列,要调整得符合要求,最少的调整次数。
输入样例
5
1 2 2 4 3
输出样例
2
思路分析
上一篇文章是在tyvj上搜题的时候手贱做的…尽管都是合唱队型都是dp但本质却完全不同呀…因为衣服的颜色(可以看作字符)要左右对称,所以类似于一个回文串,问你最少的操作次数使一个字符串成为回文串,类似于这道。
但是这一题的操作多了一个“让一个人换衣服颜色”(增加与删除等效,在多的那边删除就等于在少的那边增加),这使得字符串本身的字符可以改变了,我们不能再用之前的方法来处理了,我们需要把回文串那道题换一种更“dp”的办法来做——写状态转移方程吧。
用dp[i][j]表示以i为起点长度为j的字符串变成回文串需要的操作次数;
当j=1时本身就是回文串;
当j=2时如果c[i]==c[i+1]就是回文串。如果不是,操作次数为1(修改一个/在前后添加一个)成为回文串;
当j>=3时,考察c[i]与c[i+j-1]是否相等。如果相等就是回文串,决策:①不动 ②去掉首 ③去掉尾,如果不相等,决策:①改变首尾中一个人的颜色 ②去掉首 ③去掉尾
状态转移方程
初始化:dp[i][1]=0;
if(j==2) if(c[i]==c[i+1]) dp[i][j]=0; else dp[i][j]=1;
if(j>=3) if(c[i]==c[i+j-1]) dp[i][j]=min{dp[i+1][j-1],dp[i+1][j]+1,dp[i][j-1]+1}; else dp[i][j]=min{dp[i+1][j-1],dp[i+1][j],dp[i][j-1]}+1;