제출 #1247943

#제출 시각아이디문제언어결과실행 시간메모리
1247943dfhdfhdsfSelotejp (COCI20_selotejp)C++20
70 / 110
1096 ms460 KiB
#include <bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
static const int INF = 1e9;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    vector<int> row_mask(n);
    for(int i = 0; i < n; i++){
        string s;
        cin >> s;
        int mask = 0;
        for(int j = 0; j < m; j++){
            if (s[j] == '#')
                mask |= (1 << j);
        }
        row_mask[i] = mask;
    }

    // Precompute popcount for masks up to 2^m
    int M = 1 << m;
    vector<int> popc(M);
    for(int mask = 1; mask < M; mask++){
        popc[mask] = popc[mask >> 1] + (mask & 1);
    }

    // Precompute horizontal segments for every possible H mask (length m)
    // segs[H] = số chuỗi con liên tiếp trong H
    vector<int> segs(M, 0);
    for(int mask = 0; mask < M; mask++){
        int cnt = 0;
        for(int j = 0; j < m; j++){
            if ((mask & (1 << j)) && (j == 0 || !(mask & (1 << (j-1)))))
                cnt++;
        }
        segs[mask] = cnt;
    }

    // DP arrays
    vector<int> dp(M, INF), newdp(M, INF);
    // ban đầu, trước hàng 0 ta chưa mở dọc ở đâu, chi phí = 0
    dp[0] = 0;

    // chuyển DP qua từng hàng
    for(int i = 0; i < n; i++){
        int R = row_mask[i];
        // reset newdp
        fill(newdp.begin(), newdp.end(), INF);

        // với mỗi cấu hình mở dọc prev_mask
        for(int prev_mask = 0; prev_mask < M; prev_mask++){
            if (dp[prev_mask] == INF) continue;
            // chỉ xét next_mask là conmask của R
            // enumerate submasks of R:
            //   for(int next_mask = R; ; next_mask = (next_mask-1) & R) { ... if(next_mask==0) break; }
            // trong đó có cả next_mask=0, cho nên ta dùng do-while
            int next_mask = R;
            do {
                // chi phí khởi các băng dọc mới:
                //   mỗi bit 1 ở next_mask mà prev_mask có 0 ⇒ +1
                int start_new = popc[next_mask & ~prev_mask];
                // chi phí ngang:
                int H = R ^ next_mask;
                int cost_h = segs[H];
                int cost = dp[prev_mask] + start_new + cost_h;
                // cập nhật
                if (cost < newdp[next_mask])
                    newdp[next_mask] = cost;

                if (next_mask == 0) break;
                next_mask = (next_mask - 1) & R;
            } while(true);
        }

        // chuyển sang hàng tiếp
        dp.swap(newdp);
    }

    // đáp án: min dp[mask] ở hàng cuối (không tính thêm gì khi đóng dọc)
    int ans = *min_element(dp.begin(), dp.end());
    cout << ans << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...