PalindromeMatrix

Topcoder #枚举 #dp

枚举回文的行,考虑 \(dp_{i,j}\) 表示前 \(i\) 列和后 \(i\) 列中有 \(j\) 列为回文的列的最小代价

转移要分讨

// Author: xiaruize
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 15 + 10;

void chkmi(int &x, int y)
{
    if (y < x)
        x = y;
}

int n, m;
int col, row;
char s[N][N];
int dp[N][N];

bool isrw(int msk, int x)
{
    if ((msk >> (x - 1)) & 1)
        return true;
    return false;
}

void solve()
{
    cin >> n;
    rep(i, 1, n) cin >> (s[i] + 1);
    m = strlen(s[1] + 1);
    cin >> row >> col;
    debug(row, col);
    int res = INF;
    rep(msk, 0, (1 << n) - 1)
    {
        if (__builtin_popcount(msk) < row)
            continue;
        mms(dp, 0x3f);
        dp[0][0] = 0;
        rep(i, 1, m / 2)
        {
            int cst1 = 0, cst2 = 0, cst3 = 0;
            rep(j, 1, n / 2)
            {
                if (s[j][i] != s[n - j + 1][i])
                {
                    cst1++;
                    if ((isrw(msk, j) && s[j][i] != s[j][m - i + 1]) || (isrw(msk, n - j + 1) && s[n - j + 1][i] != s[n - j + 1][m - i + 1]))
                        cst1--;
                    else if (isrw(msk, j) && isrw(msk, n - j + 1))
                        cst1++;
                }
                if (s[j][m - i + 1] != s[n - j + 1][m - i + 1])
                {
                    cst2++;
                    if ((isrw(msk, j) && s[j][i] != s[j][m - i + 1]) || (isrw(msk, n - j + 1) && s[n - j + 1][i] != s[n - j + 1][m - i + 1]))
                        cst2--;
                    else if (isrw(msk, j) && isrw(msk, n - j + 1))
                        cst2++;
                }
                if (isrw(msk, j) || isrw(msk, n - j + 1))
                {
                    int tmp = (s[j][i] != s[j][m - i + 1]) + (s[j][i] != s[n - j + 1][i]) + (s[j][i] != s[n - j + 1][m - i + 1]);
                    if (tmp > 2)
                        tmp = 4 - tmp;
                    tmp -= (isrw(msk, j) && s[j][i] != s[j][m - i + 1]) + (isrw(msk, n - j + 1) && s[n - j + 1][i] != s[n - j + 1][m - i + 1]);
                    // assert(tmp >= 0);
                    cst3 += tmp;
                }
                else
                {
                    cst3 += (s[j][i] != s[n - j + 1][i]) + (s[j][m - i + 1] != s[n - j + 1][m - i + 1]);
                }
            }
            // if (msk == 899)
            //     debug(msk, i, cst1, cst2, cst3);
            rep(j, 0, i * 2)
            {
                chkmi(dp[i][j], dp[i - 1][j]);
                chkmi(dp[i][j + 1], dp[i - 1][j] + min(cst1, cst2));
                chkmi(dp[i][j + 2], dp[i - 1][j] + cst3);
            }
        }
        int cur = 0;
        rep(i, 1, n)
        {
            if (isrw(msk, i))
            {
                rep(j, 1, m / 2) if (s[i][j] != s[i][m - j + 1])
                    cur++;
            }
        }
        int mi = INF;
        rep(i, col, m) mi = min(mi, dp[m / 2][i]);
        res = min(res, cur + mi);
        // debug(res, msk, cur, dp[m / 2][col]);
    }
    cout << res << endl;
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int testcase = 1;
    // cin >> testcase;
    while (testcase--)
        solve();
#ifndef ONLINE_JUDGE
    cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
    cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
    return 0;
}
posted @ 2024-04-10 10:12  xiaruize  阅读(3)  评论(0)    收藏  举报