codeforces 18e dp

题意:

在n×m的一个棋盘上,每个格子有一个颜色,你可以任意改变它的颜色,改变一次的代价是1,用最小的代价达到以下条件:

  • 相邻格子的颜色均不相同。
  • 每行最多只能有2种颜色。

输出最小代价和任意一种涂色方案。

题解:

由于每行只能有两种颜色,而且相邻的颜色不同,所以每行一定是ABABA...的样子。所以直接定义:dp[i][j][k]表示前i行,第i行的第一个颜色为j,第二个颜色为k的最小代价,那么: 
dp[i][j][k]=min(dp[i−1][p][q])+cost[i][j][k],1≤p,q≤26 j≠p,k≠q

对于 j=p,k=q的情况令cost = INF即可解决

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 550;
const int MAXM = 550;
const int MAXC = 30;
const int INF = 0x3f3f3f3f;

int N, M;
char color[MAXN][MAXM];
int dp[MAXN][MAXC][MAXC];
int cost[MAXN][MAXC][MAXC];
pair <int, int> pre[MAXN][MAXC][MAXC];

void Init(){
    //初始化dp和cost
    memset(dp, 0x3f, sizeof dp);
    memset(cost, 0x3f, sizeof cost);
    for(int i = 1; i <= N; i ++){
        for(int j = 1; j <= MAXC; j ++){
            for(int k = 1; k <= MAXC; k ++){
                if(j == k)
                    continue;
                cost[i][j][k] = 0;
                for(int p = 1; p <= M; p += 2)//颜色1
                    cost[i][j][k] += (color[i][p] != ('a' + j - 1));
                for(int p = 2; p <= M; p += 2)//颜色2
                    cost[i][j][k] += (color[i][p] != ('a' + k - 1));
            }
        }
    }
    for(int i = 1; i <= MAXC; i ++)
        for(int j = 1; j <= MAXC; j ++)
            dp[1][i][j] = cost[1][i][j];
}
//输出方案
void Print(int i, int color1, int color2){
    if(i > 1)
        Print(i - 1, pre[i][color1][color2]. first, pre[i][color1][color2]. second);
    for(int i = 1; i <= M; i ++)
        if(i & 1) putchar('a' + color1 - 1);
        else putchar('a' + color2 - 1);
    putchar('\n');
}

int main(){
    scanf("%d %d", &N, &M);
    for(int i = 1; i <= N; i ++)
        scanf("%s", color[i] + 1);
    Init();
    for(int i = 1; i <= N; i ++)
        for(int j = 1; j <= MAXC; j ++)
            for(int k = 1; k <= MAXC; k ++)
                for(int p = 1; p <= MAXC; p ++)
                    for(int q = 1; q <= MAXC; q ++)
                        if(p != j && q != k)
                            if(dp[i][j][k] > dp[i - 1][p][q] + cost[i][j][k]){
                                pre[i][j][k] = make_pair(p, q);
                                //pre存上一行的颜色
                                dp[i][j][k] = dp[i - 1][p][q] + cost[i][j][k];
                            }
    int Ans = INF, ci, cj;
    for(int i = 1; i <= MAXC; i ++)
        for(int j = 1; j <= MAXC; j ++)
            if(Ans > dp[N][i][j])
                Ans = dp[N][ci = i][cj = j];
    printf("%d\n", Ans);
    Print(N, ci, cj);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/86569695