Submission #931533

#TimeUsernameProblemLanguageResultExecution timeMemory
931533WhisperSelotejp (COCI20_selotejp)C++17
110 / 110
18 ms1624 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; #define int long long #define FOR(i, a, b) for ( int i = a ; i <= b ; i++ ) #define FORD(i, a, b) for (int i = b; i >= a; i --) #define REP(i, n) for (int i = 0; i < n; ++i) #define REPD(i, n) for (int i = n - 1; i >= 0; --i) #define pii pair<int , int> #define Lg(x) 31 - __builtin_clz(x) #define MASK(i) (1LL << (i)) #define BIT(x, i) (((x) >> (i)) & 1) constexpr ll LINF = (1ll << 60); constexpr int INF = (1ll << 30); constexpr int MAX = 1e3 + 5; constexpr int Mod = 1e9 + 7; mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); void setupIO(){ #define name "Whisper" //Phu Trong from Nguyen Tat Thanh High School for gifted student srand(time(NULL)); cin.tie(nullptr)->sync_with_stdio(false); cout.tie(nullptr); // freopen(name".inp", "r", stdin); // freopen(name".out", "w", stdout); cout << fixed << setprecision(10); } template <class X, class Y> bool minimize(X &x, const Y &y){ X eps = 1e-9; if (x > y + eps) {x = y; return 1;} return 0; } template <class X, class Y> bool maximize(X &x, const Y &y){ X eps = 1e-9; if (x + eps < y) {x = y; return 1;} return 0; } int nCol, nRow; char a[MAX][MAX]; void Whisper(){ cin >> nRow >> nCol; REP(i, nRow) REP(j, nCol) cin >> a[i][j]; vector<int> F(MASK(nCol)), G(MASK(nCol), INF); G[0] = 0; REP(i, nRow) REP(j, nCol){ for (int msk = 0; msk < MASK(nCol); ++msk){ if (a[i][j] == '.'){ if (BIT(msk, j)) F[msk] = INF; else F[msk] = min(G[msk], G[msk ^ MASK(j)]); } else{ if (BIT(msk, j)){ F[msk] = min(G[msk], G[msk ^ MASK(j)] + 1); } else{ F[msk] = min(G[msk], G[msk ^ MASK(j)]); if (j == 0 || a[i][j - 1] == '.' || BIT(msk, j - 1)) F[msk]++; } } } swap(F, G); } int ans = INF; for (int msk = 0; msk < MASK(nCol); ++msk){ minimize(ans, G[msk]); } cout << ans; /* using dp[i][j][msk] as the minimum that the state i and j is the current row and column and the mask that represents what happened on the last m square, the current square, squares that are in the current row and on the left side, and square is in the previous row that are on the right side of the current square bit 0 mean that the row j is covered by a horizontal piece of tape bit 1 mean that the row j is covered by a vertical piece of tape 1. a[i][j] = '.' dp[i][j][msk] = min(dp[i][j - 1][msk], dp[i][j - 1][msk ^ MASK(j) + 1] 2. a[i][j] != '.' if (the j - th bit is 1) dp[i][j][msk] = min(dp[i][j - 1][msk]) // the previous square has the same state with current dp[i][j][msk] = min(dp[i][j - 1][msk ^ MASK(j)] + 1) // (the previous square is covered by a horizontal piece of tape so we make a new vertical piece of tap -> + 1) if (the j - th bit is 0) dp[i][j][msk] = min(dp[i][j][msk, dp[i][j][msk ^ MASK(j)] (update for new state) if (i == 0 || s[i][j - 1] == '.' || BIT(msk, j - 1)) dp[i][j][msk]++ (make a new horizontal piece of tape) 3. we can also optimize the memory by using two array F and G F(msk) : the minimum tape we need to cover all the close till i row and j column G(msk) : the minimum tape we need to cover all the colose till i row and j - 1 column */ } signed main(){ setupIO(); int Test = 1; // cin >> Test; for ( int i = 1 ; i <= Test ; i++ ){ Whisper(); if (i < Test) cout << '\n'; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...