zoukankan      html  css  js  c++  java
  • Codeforces1214D. Treasure Island (dp + Hash)

    题目链接:传送门


    思路:

    仔细观察可以发现,答案最多就是2,只要把(2,1)和(1,2)堵住就可以了。

    答案是0的情况就是初始状态下,(1,1)就已经不可达(n,m)了,很好判断。

    所以重点就是区分答案为1和答案为2的情况。

    如果答案为1的话,就说明从(1,1)到(n,m)的所有路径都经过同一个点(这样的点至少一个)。

    实际上,求出(1,1)出发可达的所有点的集合S1,和所有可达(n,m)的点S2。这里用dp来跑可以O(nm)。其中坐标要压成一维的(因为n、m的范围没有给出),否则不好开内存。

    再以到(1,1)的曼哈顿距离相同为条件,把两个点集划分成O(n+m)个集合。

    这些集合的大小的最小值,就是答案。


    代码: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 '
    '
    #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
  • 相关阅读:
    canvas绘制折线路径动画
    canvas绘制虚线图表
    BootstrapTable 行内编辑解决方案:bootstrap-table-editor
    canvas绘制图像轮廓效果
    三维场景中常用的路径动画
    三维组态部件动画解决方案
    canvas多重阴影发光效果
    萌新的算法课-方法论
    网易云ncm文件转换器
    PyCharm永久激活
  • 原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/11634501.html
Copyright © 2011-2022 走看看