zoukankan      html  css  js  c++  java
  • BZOJ4992 [Usaco2017 Feb]Why Did the Cow Cross the Road 最短路 SPFA

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ4992


    题意概括

      在一幅n*n的地图上,Amber从左上角走到右下角,每走一步需要花费时间t,每走完3步时,还要加上到达的那个格子的值。这里的3步不包括起动的那个格子。如果刚好3步到达右下角,则右下角格子的值也要算进花费中,否则不用计算进去。求最小花费。n<=100


    题解

      最短路写一写就可以了,居然不卡spfa!

      有一个点要注意:每一个点要建16条边,我就是因为少建了4条边,少了100分……

      是这样的:每走3步建一条边,与该点距离为3的点,每个一条边,共12条;与该点距离为1的点,也要建边,这个就是我万万没想到的WA掉了。这四条边的结果,还不如打暴力!当然别忘了建连向终点的5条特殊的边。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int N=100+5,M=N*N*16;
    const int dx[16]={-3, 0, 3, 0,-2,-2, 2, 2,-1,-1, 1, 1, 1,-1, 0, 0};
    const int dy[16]={ 0,-3, 0, 3, 1,-1, 1,-1, 2,-2, 2,-2, 0, 0, 1,-1};
    int n;
    LL a[N][N],t;
    struct Edge{
    	int cnt,y[M],nxt[M],fst[N*N];
    	LL z[M];
    	void set(){
    		cnt=0;
    		memset(y,0,sizeof y);
    		memset(z,0,sizeof z);
    		memset(nxt,0,sizeof nxt);
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b,LL c){
    		cnt++;
    		y[cnt]=b,z[cnt]=c;
    		nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }e;
    bool check(int x,int y){
    	return 1<=x&&x<=n&&1<=y&&y<=n;
    }
    int hash(int x,int y){
    	return (x-1)*n+y-1;
    }
    void adden(int x,int y){
    	if (!check(x,y))
    		return;
    	e.add(hash(x,y),hash(n,n),t*(abs(n-x)+abs(n-y)));
    }
    LL dis[N*N];
    bool f[N*N];
    int q[N*N],qmod,head,tail;
    void spfa(){
    	for (int i=0;i<n*n;i++)
    		dis[i]=1LL<<55;
    	memset(f,0,sizeof f);
    	qmod=n*n+1;
    	head=0,tail=0;
    	q[tail=(tail+1)%qmod]=0;
    	dis[0]=0;
    	f[0]=1;
    	while (head!=tail){
    		int x=q[head=(head+1)%qmod];
    		f[x]=0;
    		for (int i=e.fst[x];i;i=e.nxt[i]){
    			int y=e.y[i];
    			LL z=e.z[i];
    			if (dis[y]>dis[x]+z){
    				dis[y]=dis[x]+z;
    				if (!f[y]){
    					f[y]=1;
    					q[tail=(tail+1)%qmod]=y;
    				}
    			}
    		}
    	}
    }
    int main(){
    	scanf("%d%lld",&n,&t);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++)
    			scanf("%lld",&a[i][j]);
    	e.set();
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=n;j++){
    			int x=hash(i,j);
    			for (int k=0;k<16;k++){
    				int i_=i+dx[k],j_=j+dy[k];
    				if (check(i_,j_))
    					e.add(x,hash(i_,j_),t*3LL+a[i_][j_]);
    			}
    		}
    	adden(n-2,n),adden(n-1,n-1),adden(n,n-2),adden(n-1,n),adden(n,n-1);
    	spfa();
    	printf("%lld",dis[hash(n,n)]);
    	return 0;
    }
    

      

  • 相关阅读:
    array and ram
    char as int
    pointer of 2d array and address
    Install SAP HANA EXPRESS on Google Cloud Platform
    Ubuntu remount hard drive
    Compile OpenSSL with Visual Studio 2019
    Install Jupyter notebook and tensorflow on Ubuntu 18.04
    Build OpenCV text(OCR) module on windows with Visual Studio 2019
    Reinstall VirtualBox 6.0 on Ubuntu 18.04
    Pitfall in std::vector<cv::Mat>
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ4992.html
Copyright © 2011-2022 走看看