zoukankan      html  css  js  c++  java
  • 「BZOJ 1698」「USACO 2007 Feb」Lilypad Pond 荷叶池塘「最短路」

    题解

    从一个点P可以跳到另一个点Q,如果Q是水这条边就是1,如果Q是荷叶这条边权值是0。可以跑最短路并计数

    问题是边权为0的最短路计数没有意义(只是荷叶的跳法不同),所以我们两个能通过荷叶间接连通的点连一条边权为1的边就好

    #include <algorithm>
    #include <cstdio>
    #include <queue>
    using namespace std;
    
    #define id(x, y) ((x - 1) * m + y)
    #define valid(x, y) (x >= 1 && y >= 1 && x <= n && y <= m)
    #define pt(x, y) (a[x][y] == 1 || a[x][y] == 3 || a[x][y] == 4)
    
    const int N = 35;
    const int dx[] = {1, 1, -1, -1, 2, 2, -2, -2};
    const int dy[] = {2, -2, 2, -2, 1, -1, 1, -1};
    
    struct Edge {
    	int v, nxt;
    } e[N * N * N * N];
    int n, m, a[N][N], hd[N * N], p;
    bool edge[N * N][N * N];
    
    void clr() {
    	fill(hd + 1, hd + n * m + 1, -1); p = 0;
    }
    void add(int u, int v) {
    	if(edge[u][v] || u == v) return ;
    	edge[u][v] = 1;
    	e[p] = (Edge) {v, hd[u]}; hd[u] = p ++;
    }
    bool vis[N * N];
    void dfs(int x, int y, int cur) {
    	vis[id(x, y)] = 1;
    	for(int k = 0; k < 8; k ++) {
    		int nx = x + dx[k], ny = y + dy[k];
    		if(valid(nx, ny) && !vis[id(nx, ny)]) {
    			if(a[nx][ny] == 1) dfs(nx, ny, cur);
    			else add(cur, id(nx, ny));
    		}
    	}
    }
    int dis[N * N];
    long long cnt[N * N]; 
    void bfs(int s, int t) {
    	fill(dis + 1, dis + n * m + 1, -1);
    	queue<int> q; q.push(s); cnt[s] = 1; dis[s] = 0;
    	while(q.size()) {
    		int u = q.front(); q.pop();
    		for(int i = hd[u]; ~ i; i = e[i].nxt) {
    			int v = e[i].v;
    			if(dis[v] == -1) {
    				dis[v] = dis[u] + 1;
    				cnt[v] = cnt[u]; q.push(v);
    			} else if(dis[v] == dis[u] + 1) {
    				cnt[v] += cnt[u];
    			}
    		}
    	}
    }
    int main() {
    	scanf("%d%d", &n, &m); clr();
    	int s = 1, t = 1;
    	for(int i = 1; i <= n; i ++) {
    		for(int j = 1; j <= m; j ++) {
    			scanf("%d", &a[i][j]);
    			if(a[i][j] == 3) s = id(i, j);
    			if(a[i][j] == 4) t = id(i, j);
    		}
    	}
    	for(int i = 1; i <= n; i ++) {
    		for(int j = 1; j <= m; j ++) if(a[i][j] == 3 || a[i][j] == 0) {
    			fill(vis + 1, vis + n * m + 1, 0);
    			dfs(i, j, id(i, j));
    		}
    	}
    	bfs(s, t);
    	if(cnt[t]) printf("%d
    %lld
    ", dis[t] == 0 ? 0 : dis[t] - 1, cnt[t]);
    	else puts("-1");
    	return 0;
    }
    
    
    
  • 相关阅读:
    Android 适配知识点
    Android Studio各种快捷功能及好用的插件
    81.Android之沉浸式状态栏攻略
    8.Android 系统状态栏沉浸式/透明化解决方案
    为开发者准备的 Android 函数库(2016 年版)
    GitHub 上 57 款最流行的开源深度学习项目
    7.Android开源项目WheelView的时间和地址联动选择对话框
    6.初探Asynctask
    5.Android消息推送机制简单例子
    让你Android开发更简单
  • 原文地址:https://www.cnblogs.com/hongzy/p/11097071.html
Copyright © 2011-2022 走看看