• 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
    ",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可以预处理
    //倒叙输出 
    

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

  • 相关阅读:
    Largest Rectangle in Histogram
    Valid Sudoku
    Set Matrix Zeroes
    Unique Paths
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
    Path Sum II
    Path Sum
    Validate Binary Search Tree
    新手程序员 e
  • 原文地址:https://www.cnblogs.com/lichangjian/p/14880688.html
Copyright © 2020-2023  润新知