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;
}
$$Life \quad is \quad fantastic!$$