zoukankan      html  css  js  c++  java
  • Luogu 1606 [USACO07FEB]白银莲花池Lilypad Pond

    感觉应当挺简单的,但是弄了好久……菜死了

    如果不考虑那些为$1$的点,直接跑个最短路计数就好了,但是我们现在有一些边可以不用付出代价,那么只要在连边的时候先预处理搜一下就好了。

    原来的想法是拆点,但是这样子不好连边,所以直接把点权转化到边权上来。

    注意到起点其实不用付出代价,那么最后的答案就是$dis_ed - 1$。

    时间复杂度上界是$O(n^4 + n^2log(n^2))$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    typedef long long ll;
    typedef pair <ll, int> pin;
    
    const int N = 1005;
    const int M = 2e5 + 5;
    const int L = 35;
    const int dx[] = {-1, -2, -2, -1, 1, 2, 2, 1};
    const int dy[] = {-2, -1, 1, 2, 2, 1, -1, -2};
    const ll inf = 0x3f3f3f3f3f3f3f3f;
    
    int n, m, a[L][L], tot = 0, head[N];
    ll dis[N], cnt[N];
    bool vis[N], ins[L][L];
    
    struct Edge {
        int to, nxt;
    } e[M];
    
    inline void add(int from, int to) {
        e[++tot].to = to;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline int id(int x, int y) {
        return (x - 1) * m + y;
    }
    
    void dfs(int nowId, int x, int y) {
        ins[x][y] = 1;
        for(int i = 0; i < 8; i++) {
            int tox = x + dx[i], toy = y + dy[i];
            if(tox < 1 || tox > n || toy < 1 || toy > m) continue;
            if(ins[tox][toy]) continue;
            if(a[tox][toy] == 1) dfs(nowId, tox, toy);
            else ins[tox][toy] = 1, add(nowId, id(tox, toy));
        }
    }
    
    priority_queue <pin> Q;
    void dij(int st) {
        memset(dis, 0x3f, sizeof(dis));
        cnt[st] = 1LL, dis[st] = 0LL;
        Q.push(pin(0, st));
        for(; !Q.empty(); ) {
            int x = Q.top().second; Q.pop();
            if(vis[x]) continue;
            vis[x] = 1;
            for(int i = head[x]; i; i = e[i].nxt) {
                int y = e[i].to;
                if(dis[y] > dis[x] + 1) {
                    dis[y] = dis[x] + 1;
                    cnt[y] = cnt[x];
                    Q.push(pin(-dis[y], y));
                } else if(dis[y] == dis[x] + 1) {
                    cnt[y] += cnt[x];
                }
            }
        } 
    }
    
    int main() {
    //    freopen("testdata.in", "r", stdin);
        
        read(n), read(m);
        int st, ed;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++) {
                read(a[i][j]);
                if(a[i][j] == 3) st = id(i, j);
                if(a[i][j] == 4) ed = id(i, j);
            }
        
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= m; j++)
                if(a[i][j] == 0 || a[i][j] == 3) {
                    memset(ins, 0, sizeof(ins));
                    dfs(id(i, j), i, j);
                } 
        
        dij(st);
        
        if(dis[ed] == inf) puts("-1");
        else printf("%lld
    %lld
    ", dis[ed] - 1, cnt[ed]);
        
        return 0;
    }
    View Code
  • 相关阅读:
    Oracle中对多行查询结果进行拼接
    DX使用随笔--NavBarControl
    DX使用随记--其他
    DX使用随记--GroupControl
    DX使用随记--ImageComboBoxEdit
    DX使用随记--TabControl
    Oracle相关
    DX使用随记--GridControl
    一个NPOI导出到excel文件的范例记录
    python数据类
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9856811.html
Copyright © 2011-2022 走看看