zoukankan      html  css  js  c++  java
  • 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可以预处理
    //倒叙输出 
    

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

  • 相关阅读:
    cocos2d-x 2.2 study ------------------------ 双击事件(转)
    cocos2d-x打包Android
    cocos2d-x在win7下的android交叉编译环境
    Cocos2d-x之CCImage深入分析
    Eclipse开发C/C++之使用技巧小结
    TortoiseSVN安装使用
    cocos2d-x 2.2 study ------------------------ CCCallFunC家族
    cocos2d-x改底层之动态改变UIListView中的某项在链表中的位置
    汇编语言,以10进制的方式显示数字
    JVM
  • 原文地址:https://www.cnblogs.com/lichangjian/p/14880688.html
Copyright © 2011-2022 走看看