codeforces 18E Flag 2 (dp)

来源:互联网 发布:js混淆还原工具 编辑:程序博客网 时间:2024/06/01 09:38

题意:

给出一个字符串的矩阵,现在要求按这样的规律变换:

1、每行只能有两中字母。(每列可以多个字母)

2、任意相邻的字母不能相同。

求最少的操作数,并且要把变换后的矩阵打印下来。

题解:

分析下这些要求,会发现一行中必须要是这样的形式才能满足条件:ABABAB....。

那么我们定义状态dp[i][A][B]表示第i行用了字母A,B这两个字母构成形式ABABA...(有先后顺序的)然后按行dp即可。勉强过。。


#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<map>using namespace std;//typedef long long lld;const int oo=0x3f3f3f3f;//const lld OO=1LL<<61;const int MOD=(1e9)+7;const int maxn=505;int dp[maxn][26][26];struct{    int A,B;}pre[maxn][26][26];char maze[maxn][maxn];int n,m;int cost(int i,int a,int b){    char A=a+'a',B=b+'a';    int ans=0;    for(int j=1;j<=m;j++)    {        if(j&1) ans+=(maze[i][j]!=A);        else ans+=(maze[i][j]!=B);    }    return ans;}void DP(){    memset(dp,0x3f,sizeof dp);    for(int A=0;A<26;A++)        for(int B=0;B<26;B++)            if(A!=B)                dp[1][A][B]=cost(1,A,B);    for(int i=2;i<=n;i++)    {        for(int A=0;A<26;A++)        {            for(int B=0;B<26;B++)            {                if(A==B)continue;                int c=cost(i,A,B);                for(int a=0;a<26;a++)                {                    if(a==A)continue;                    for(int b=0;b<26;b++)                    {                        if(b==B)continue;                        if(a==b)continue;                        if(dp[i-1][a][b]==oo)continue;                        if(dp[i][A][B]>dp[i-1][a][b]+c)                        {                            dp[i][A][B]=dp[i-1][a][b]+c;                            pre[i][A][B].A=a;                            pre[i][A][B].B=b;                        }                    }                }            }        }    }    int ans=oo,A,B;    for(int i=0;i<26;i++)        for(int j=0;j<26;j++)            if(ans>dp[n][i][j])            {                ans=dp[n][i][j];                A=i;                B=j;            }    printf("%d\n",ans);    for(int i=n;i>=1;i--)    {        for(int j=1;j<=m;j++)        {            if(j&1) maze[i][j]=A+'a';            else maze[i][j]=B+'a';        }        int a=A,b=B;        A=pre[i][a][b].A;        B=pre[i][a][b].B;    }    for(int i=1;i<=n;i++)        printf("%s\n",maze[i]+1);}int main(){    while(scanf("%d %d",&n,&m)!=EOF)    {        for(int i=1;i<=n;i++)            scanf("%s",maze[i]+1);        DP();    }    return 0;}/**3 4aaaabbbbcccc3 3abaabazzz*/


0 0
原创粉丝点击