• 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;
    }
    
    
  • 相关阅读:
    Delphi中QuotedStr介绍及使用
    <<编写可维护的JavaScript>>之避免使用全局变量
    JavaScript中的继承模式总结(九)
    JavaScript中的继承(原型链)
    Javascript中函数的四种调用方式
    apply()和call()的区别
    在mui中遇到的内容覆盖导航栏的问题
    相等(==)运算符和等同(===)运算符之间的区别
    理解Javascript参数中的arguments对象
    Javascript之类型检测(一)
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14544853.html
Copyright © 2020-2023  润新知