P3847 调整队形

题意

P3847 调整队形

给定长为\(n\)的颜色序列,颜色为\(1\)\(n\),问最少经过多少次操作能让颜色序列左右对称

操作有添加,删除,插入,替换颜色

\(n \le 3000\)

思路

仔细分析题目题解可以发现:

  • 在队伍中任两个人中间插入一个人(衣服颜色依要求而定)
  • 剔掉一个人

这两个操作是没必要的,因为插入一个人的状态一定包含在加入一个人的状态里面,同理剔除一人和加入一个人等效

所有我们就只需要处理加入一个人和换颜色即可

\(f[i][j]\)表示\(i\)\(j\)对称需要的最小操作次数

  • 加入一个人

\(f[i][j]=\min(\min(f[i][j-1]+1,f[i+1][j]+1),f[i][j])\)

  • 换颜色

\(f[i][j]=\min(f[i+1][j-1],f[i][j])\)

\(code\)

/*
@ author:pyyyyyy/guhl37
-----思路------

-----debug-------

*/
#include<bits/stdc++.h>
using namespace std;
const int N=3333;
int f[N][N],a[N];
int n;
int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	memset(f,0x3f3f3f,sizeof(f));
	for(int i=1;i<=n;++i)
	{
		for(int j=i;j;--j)
		{
			if(i==j) f[i][j]=0;
			else if(a[i]==a[j]&&j+1>i-1) f[j][i]=0;
		}
	}
	for(int i=1;i<=n;++i)
	{
		for(int j=i;j;--j)
		{
			if(a[i]==a[j]&&j+1<=i-1) {f[j][i]=f[j+1][i-1];continue;}
			f[j][i]=min(min(f[j][i-1]+1,f[j][i]),f[j+1][i]+1);
			f[j][i]=min(f[j+1][i-1]+1,f[j][i]);
		}
	}
	cout<<f[1][n];
	return 0;
}
posted @ 2020-06-14 21:46  pyyyyyy  阅读(157)  评论(0编辑  收藏  举报