CF18E Flag 2

啊很久没写博客了

晚上熬夜熬太晚了导致下午很颓废,写个博客休息一下

进入正题……

首先题目描述说一行最多有两种颜色,而且相邻两格颜色不同,于是可以得出每一行都是由两个不同的字符交替组成的(然后我们就枚举他)

首先定义dp[i][j][k]表示第i行的第一个和第二个字符分别是j和k时最小花费,price[i][j][k]为从原状态转移到第一个和第二个字符分别为j和k时的花费,price是可以被预处理的

然后可以得到状态转换方程dp[i][j][k]=min(dp[i][j][k],dp[i-1][y][u]+price[i][j][k])(其中y,u为i-1时的j,k)

然后第一小问就做完了

然后是第二小问

第二小问因为我们求出了dp[n][i][j]和price[n][i][j],然后我们就可以倒退

然后这个题我们就做完了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long n,m;
char c;
long long shu[505][505],price[505][30][30],dp[505][30][30];
void shuchu(long long wz,long long l,long long r)
{
	if(wz==0)
	{
		return;
	}
	long long bj=0,ll=dp[wz][l][r]-price[wz][l][r];
	for(int i=0;i<26;i++)
	{
		if(bj==1)
		{
			break;
		}
		if(i==l)
		{
			continue;
		}
		for(int j=0;j<26;j++)
		{
			if(j==r)
			{
				continue;
			}
			if(dp[wz-1][i][j]==ll)
			{
				shuchu(wz-1,i,j);
				bj=1;
				break;
			}
		}
	}
	for(int i=1;i<=m;i++)
	{
		if(i%2==1)
		{
			cout<<(char)(l+'a');
		}else
		{
			cout<<(char)(r+'a');
		}
	}
	cout<<endl;
	return;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>c;
			shu[i][j]=(c-'0')-49;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<26;j++)
		{
			for(int k=0;k<26;k++)
			{
				dp[i][j][k]=9999999999;
				for(int wz=1;wz<=m;wz++)
				{
					if((wz%2==1)&&shu[i][wz]!=j)
					{
						price[i][j][k]++;
					}else if((wz%2==0)&&shu[i][wz]!=k)
					{
						price[i][j][k]++;
					}
				}
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<26;j++)
		{
			for(int k=0;k<26;k++)
			{
				if(j==k)continue;
				for(int y=0;y<26;y++)
				{
					if(y==j)continue;
					for(int u=0;u<26;u++)
					{
						if(u==y||u==k)continue;
						dp[i][j][k]=min(dp[i][j][k],dp[i-1][y][u]+price[i][j][k]);
					}
				}
			}
		}
	}
	long long ans=9999999999999,l=0,r=0;
	for(int i=0;i<26;i++)
	{
		for(int j=0;j<26;j++)
		{
			if(dp[n][i][j]<ans)
			{
				l=i;
				r=j;
				ans=dp[n][i][j];
			}
		}
	}
	printf("%lld\n",ans);
	shuchu(n,l,r);
	return 0;
}
//看着挺容易的……
//因为每行最多两个字符而且相邻不能一致,所以必然是交替出现
//那就枚举……枚举这一行的两个字母和上一行的两个字母,dp[i][j][k]表示第i行,第一个字母是j第二个字母是k时的最小代价
//显而易见1 dp[i][j][k]=min(dp[i][j][k],dp[i-1][y][u]+price[i-1][y][u])(price[i][j][k]为将原序列转化成上面表述的代价)
//显而易见1.5 price可以预处理
//倒叙输出 

  (祝大家明天端午节快乐)

 

posted @ 2021-06-13 17:29  lichangjian  阅读(43)  评论(0编辑  收藏  举报