CF18E Flag 2

原题链接

  • 题意:给出 (n imes m) 的矩阵,全部由26个小写字母构成,然后要求构造一种矩阵,要求和原矩阵差别最小,保证每行只有两种字母,列不做要求。保证每个字母相邻是不相同的。
  • 题解:没想到构造题也能用dp来做,就是按行dp,可以发现,就好像是枚举所有可能性,然后取 (max) 的操作,不过就是这是按照上一行的状态推下来的,设 (dp_{i,a,b}) 就是第i行然后选择 (a,b) 交替最小花费,然后是通过上一行可行状态转移过来,即$$dp_{i, a, b} = min (dp_{i-1,c, d} + cost_{i, a, b} ) (c eq d , c eq a, a eq b, b eq d)$$
    (cost_{i, a, b}) 应当预处理,时间复杂度为 (O(26^{4}n + 26^{2}nm))
  • 代码:
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>


using namespace std;
typedef long long ll;
typedef long double lb;
const ll N = 555;
const  lb eps = 1e-8;
char mp[N][N];
int dp[N][27][27];
int Cost[N][27][27];
pair<char, char> pre[N][27][27], Now;

int n, m;
int cost(int i, char a, char b) {
    int ret = 0;
    for (int j = 1; j <= m; j++) {
        if (j & 1) {
            if (mp[i][j] != a)ret++;
        } else if (mp[i][j] != b)ret++;
    }
    return ret;
}
void change(int i, char a, char b) {
    for (int j = 1; j <= m; j++) {
        if (j & 1) {
           mp[i][j]= a;
        } else mp[i][j] = b;
    }
}
void solve() {
    cin >> n >> m;
    memset(dp, 0x3f, sizeof dp);
    for (int i = 'a'; i <= 'z'; i++) {
        for (int j = 'a'; j <= 'z'; j++) {
            dp[0][i - 'a'][j - 'a'] = 0;
        }
    }
    for (int i = 1; i <= n; i++) cin >> (mp[i] + 1);
    for (int i = 1; i <= n; i++) {
        for (char a = 'a'; a <= 'z'; a++) {
            for (char b = 'a'; b <= 'z'; b++) {
                if (a == b)continue;
                Cost[i][a-'a'][b-'a'] = cost(i, a, b);
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        for (char a = 'a'; a <= 'z'; a++) {
            for (char b = 'a'; b <= 'z'; b++) {
                if (a == b)continue;
                for (char c = 'a'; c <= 'z' ; c++) {
                    for (char d = 'a'; d <= 'z'; d++) {
                        if (c == d)continue;
                        if (c == a)continue;
                        if (d == b)continue;
                        int cos = Cost[i][a-'a'][b- 'a'];
                        if (dp[i][a - 'a'][b - 'a'] > dp[i-1][c - 'a'][d - 'a'] + cos) {
                            dp[i][a - 'a'][b - 'a'] = min(dp[i][a - 'a'][b - 'a'], dp[i-1][c - 'a'][d - 'a'] + cos);
                            pre[i][a - 'a'][b - 'a'] = make_pair(c, d);
                        }
                    }
                }
            }
        }
    }
    int ans = 0x3f3f3f3f;
    for (int i = 'a'; i <= 'z'; i++) {
        for (int j = 'a'; j <= 'z'; j++) {
            if (i == j)continue;

            if (ans > dp[n][i - 'a'][j - 'a']) {
                ans = dp[n][i - 'a'][j - 'a'];
                Now.first = i, Now.second = j;
            }
        }
    }
    int now = n;
    change(now,  Now.first, Now.second);
    while (Now.first != 0 && Now.second != 0) {
        Now = pre[now][Now.first - 'a'][Now.second - 'a'];
        change(--now, Now.first,Now.second);
    }
    cout << ans << endl;
    for (int i = 1; i <= n; i++) {
        cout << (mp[i] + 1) << endl;
    }
}
signed main() {
    ios::sync_with_stdio(0);
    int t = 1;//cin >> t;
    while (t--) solve();
    return 0;
}

原文地址:https://www.cnblogs.com/Xiao-yan/p/14544853.html