Codeforces1214D. Treasure Island (dp + Hash)

Keywords: iOS

Title Link: Portal

 

Ideas:

It can be found by careful observation that the answer is at most 2. Just block (2, 1) and (1, 2).

When the answer is 0, it means that in the initial state, (1, 1) can't reach (n, m). It's good to judge.

So the point is to distinguish the case where the answer is 1 and the answer is 2.

If the answer is 1, all paths from (1, 1) to (n, m) pass through the same point (at least one such point).

In fact, the set S1 of (1,1) starting reachable points and S2 of (n, m) starting reachable points are obtained. You can run with dp here, O (nm). The coordinates should be compressed into one dimension (because the range of N and M is not given), otherwise it is not easy to open memory.

On the condition that the Manhattan distance to (1,1) is the same, the two point sets are divided into O(n+m) sets.

The minimum size of these sets is the answer.

 

Code: O (nm)

#include <bits/stdc++.h>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 1000005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)

using namespace std;
typedef long long ll;
typedef double db;

int n, m;
inline int getx(int t) {
    return t / m;
}
inline int gety(int t) {
    return t % m;
}
inline int gett(int x, int y) {
    return x*m + y;
}

char s[N];
bool vis11[N], visnm[N];
int main()
{
    cin >> n >> m;
    memset(vis11, false, sizeof vis11);
    memset(visnm, false, sizeof visnm);
    for (int i = 0; i < n; i++)
        scanf("%s", s + i*m);
    vis11[0] = visnm[n*m-1] = true;
    for (int t = 1; t < n*m-1; t++) {
        int x = getx(t), y = gety(t);
        if (s[t] == '#') continue;
        if (x == 0) {
            int pret = gett(x, y-1);
            vis11[t] = vis11[pret];
        }
        else if (y == 0) {
            int pret = gett(x-1, y);
            vis11[t] = vis11[pret];
        }
        else {
            int pret1 = gett(x, y-1);
            int pret2 = gett(x-1, y);
            vis11[t] = vis11[pret1] || vis11[pret2];
        }
    }
    for (int t = n*m-2; t > 0; t--) {
        int x = getx(t), y = gety(t);
        if (s[t] == '#')
            continue;
        if (x == n-1) {
            int pret = gett(x, y+1);
            visnm[t] = visnm[pret];
        }
        else if (y == m-1) {
            int pret = gett(x+1, y);
            visnm[t] = visnm[pret];
        }
        else {
            int pret1 = gett(x, y+1);
            int pret2 = gett(x+1, y);
            visnm[t] = visnm[pret1] || visnm[pret2];
        }
    }
    int ans = 2;
    for (int d = 1; d < n+m-2; d++) {
        int x = 0, y = d;
        if (y >= m) {
            y = m-1;
            x = d-y;
        }
        int cnt = 0;
        for (; x < n && y >= 0; x++, y--) {
            int tmpt = gett(x, y);
            if (vis11[tmpt] && visnm[tmpt])
                cnt++;
        }
        if (cnt == 0) {
            ans = 0;
            break;
        }
        if (cnt == 1)
            ans = 1;
    }
    cout << ans << endl;
    return 0;
}
View Code

Posted by magie on Sat, 23 May 2020 07:44:10 -0700