zoukankan      html  css  js  c++  java
  • 洛谷 P5195 【[USACO05DEC]Knights of Ni S】

    分层图题解很少啊,来个分层图哒


    这道题一开始看,我是想的跑两次最短路,一次从起点跑,一次从终点跑,然后枚举每一个灌木,但是因为起点的时候不能走骑士,所以会(WA),只有(60)分。正解分层图最短路,在找到灌木的时候,向骑士那一层连一条边即可,从起点跑一遍最短路即可。

    这里用的(SPFA) SPFA没有SPFA!!!:

    #include <bits/stdc++.h>
    using namespace std;
    int n , m , s , tot , p;
    int a[1010][1010]  , dis[2000010] , vis[2000010];
    vector<int> e[2000010];
    int id(int x , int y){	//二维压一维 
    	return (x - 1) * m + y;
    }
    void add(int x , int y){
    	e[x].push_back(y);
    }
    void spfa(int k){
    	memset(dis , 127 , sizeof(dis));
    	memset(vis , 0 , sizeof(vis));
    	queue<int> q;
    	vis[k] = 1;
    	dis[k] = 0;
    	q.push(k);
    	while(!q.empty()){
    		int x = q.front();
    		q.pop();
    		vis[x] = 1;
    		for(int i = 0; i < e[x].size(); i++){
    			int nx = e[x][i];
    			if(dis[nx] > dis[x] + 1){
    				dis[nx] = dis[x] + 1;
    				if(!vis[nx]){
    					vis[nx] = 1;
    					q.push(nx);
    				}
    			}
    		}
    	}
    }
    int main(){
    	cin >> m >> n;
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= m; j++)
    			cin >> a[i][j];
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= m; j++){
    			if(a[i][j] == 1) continue;
    			if(a[i][j] == 2) s = id(i , j);
    			if(a[i][j] == 3) p = id(i , j);
    			if(a[i][j] == 4) add(id(i , j) , id(i , j) + n * m);
    			if((a[i - 1][j] == 0 || a[i - 1][j] == 2 || a[i - 1][j] == 4) && i != 1) add(id(i , j) , id(i - 1 , j));
    			if((a[i + 1][j] == 0 || a[i + 1][j] == 2 || a[i + 1][j] == 4) && i != n) add(id(i , j) , id(i + 1 , j));
    			if((a[i][j - 1] == 0 || a[i][j - 1] == 2 || a[i][j - 1] == 4) && j != 1) add(id(i , j) , id(i , j - 1));
    			if((a[i][j + 1] == 0 || a[i][j + 1] == 2 || a[i][j + 1] == 4) && j != m) add(id(i , j) , id(i , j + 1));
    			if((a[i - 1][j] == 0 || a[i - 1][j] == 2 || a[i - 1][j] == 4 || a[i - 1][j] == 3) && i != 1) add(id(i , j) + n * m , id(i - 1 , j) + n * m);	//向上一层连边 
    			if((a[i + 1][j] == 0 || a[i + 1][j] == 2 || a[i + 1][j] == 4 || a[i + 1][j] == 3) && i != n) add(id(i , j) + n * m , id(i + 1 , j) + n * m);
    			if((a[i][j - 1] == 0 || a[i][j - 1] == 2 || a[i][j - 1] == 4 || a[i][j - 1] == 3) && j != 1) add(id(i , j) + n * m , id(i , j - 1) + n * m);
    			if((a[i][j + 1] == 0 || a[i][j + 1] == 2 || a[i][j + 1] == 4 || a[i][j + 1] == 3) && j != m) add(id(i , j) + n * m , id(i , j + 1) + n * m);
    		}
    	spfa(s);
    	cout << dis[p + n * m] - 1;	//走向上一层的时候,花费了一天,减去 
    	return 0;
    }
    
  • 相关阅读:
    hdu 5648 DZY Loves Math 组合数+深搜(子集法)
    hdu 5647 DZY Loves Connecting 树形DP
    hdu 4550 卡片游戏 贪心
    hdu 5646 DZY Loves Partition 二分+数学分析+递推
    hdu 2196 Computer 树形DP
    poj 2342 Anniversary party 树形DP入门
    Vijos P1003 等价表达式 随机数+单调栈
    【BZOJ】1044: [HAOI2008]木棍分割 二分+区间DP
    【BZOJ】1925: [Sdoi2010]地精部落 DP+滚动数组
    【BZOJ】1012: [JSOI2008]最大数maxnumber 树状数组求区间最值
  • 原文地址:https://www.cnblogs.com/bzzs/p/13740962.html
Copyright © 2011-2022 走看看