Description
给出一个n×m的矩阵,每个位置可以染一种颜色,颜色共16种,用′a′~′z′表示,先给出初始染色状态,问至少要改变多少个位置的颜色才能使得满足以下两个条件:相邻两个格子颜色不同,一行至多两种不同的颜色
Input
第一行两个整数n,m表示矩阵行列数,之后输入一个n×m的字符矩阵表示初始染色状态(1≤n,m≤500)
Output
输出使得矩阵满足条件所需修改的最少颜色数和修改后的矩阵染色状态,多组解输出任意一组
Sample Input
3 4
aaaa
bbbb
cccc
Sample Output
6
abab
baba
acac
Solution
由于一行至多两种颜色且相邻两个格子颜色不同,所以让m>1时,一行的状态必然是xyxy...,其中x,y表示两种不同的颜色,以cost[i][x][y]表示把第i行变成
dp[i+1][xx][yy]=min(dp[i+1][xx][yy],dp[i][x][y]+cost[i+1][xx][yy]),x≠xx,y≠yy,x≠y,xx≠yy
答案即为min(dp[n][x][y],x≠y),具体方案看当前状态是由哪个状态转移过来即可得到,时间复杂度O(264n)
当m=1时,以dp[i][x]表示把第i行变成
答案即为min(dp[n][x]),具体方案同理,时间复杂度O(262n)
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=505;
int n,m,a[maxn][maxn],f[maxn][26],dp[maxn][26][26],cost[maxn][26][26];
char s[maxn];
void output0(int pos,int x)
{
if(pos>1)
{
for(int y=0;y<26;y++)
if(x!=y&&(f[pos-1][y]+(a[pos][1]!=x)==f[pos][x]))
{
output0(pos-1,y);
break;
}
}
printf("%c\n",x+'a');
}
void output(int pos,int x,int y)
{
if(pos>1)
{
int flag=0;
for(int xx=0;xx<26;xx++)
if(x!=xx)
{
for(int yy=0;yy<26;yy++)
if(y!=yy&&xx!=yy)
{
if(dp[pos-1][xx][yy]+cost[pos][x][y]==dp[pos][x][y])
{
output(pos-1,xx,yy);
flag=1;
break;
}
}
if(flag)break;
}
}
for(int i=1;i<=m;i++)
if(i&1)printf("%c",x+'a');
else printf("%c",y+'a');
printf("\n");
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=m;j++)a[i][j]=s[j]-'a';
}
if(m==1)
{
memset(f,INF,sizeof(f));
for(int x=0;x<26;x++)
if(x!=a[1][1])f[1][x]=1;
else f[1][x]=0;
for(int i=1;i<n;i++)
for(int x=0;x<26;x++)
for(int y=0;y<26;y++)
if(x!=y)
f[i+1][y]=min(f[i+1][y],f[i][x]+(a[i+1][1]!=y));
int ans=INF,x0;
for(int x=0;x<26;x++)
if(f[n][x]<ans)
ans=f[n][x],x0=x;
printf("%d\n",ans);
output0(n,x0);
}
else
{
for(int i=1;i<=n;i++)
for(int x=0;x<26;x++)
for(int y=0;y<26;y++)
if(x!=y)
for(int j=1;j<=m;j++)
if((j&1)&&a[i][j]!=x||!(j&1)&&a[i][j]!=y)
cost[i][x][y]++;
memset(dp,INF,sizeof(dp));
for(int x=0;x<26;x++)
for(int y=0;y<26;y++)
dp[1][x][y]=cost[1][x][y];
for(int i=1;i<n;i++)
for(int x=0;x<26;x++)
for(int y=0;y<26;y++)
if(x!=y)
for(int xx=0;xx<26;xx++)
if(x!=xx)
for(int yy=0;yy<26;yy++)
if(y!=yy&&xx!=yy)
dp[i+1][xx][yy]=min(dp[i+1][xx][yy],dp[i][x][y]+cost[i+1][xx][yy]);
int ans=INF,x0,y0;
for(int x=0;x<26;x++)
for(int y=0;y<26;y++)
if(x!=y&&dp[n][x][y]<ans)
ans=dp[n][x][y],x0=x,y0=y;
printf("%d\n",ans);
output(n,x0,y0);
}
return 0;
}