zoukankan      html  css  js  c++  java
  • [BalticOI 2011]Switch the Lamp On

    题目

    原题链接

    解说

    先从建图说起。

    显然如果一个格子内符号为 ,那么我们不需要转动元件就可以从左上角走到右下角,即从左上角走到右下角走了一条边权为(0)的边,而如果想从左下角走到右上角则需要转动一次元件,也可以抽象为从左上角走到右下角走了一条边权为(1)的边。符号为 / 时与之同理。

    图建好之后我们就可以直接跑最短路了……吗?

    如果我们放纵一下自己开(O2)的话确实可以轻松水过,但是这并不是我们希望看到的结果。

    下面展示一下硬跑迪杰斯特拉和(SPFA)的优秀战果。

    迪杰斯特拉(TLE) (88)

    SPFA(TLE) (86)

    这不尴尬了吗[托腮] [托腮]

    显然我们需要进行某些改良才行。不难发现在这道题中边权只有(0)(1)两种,我们应该充分利用这一特点。显然我们应该尽可能走边权为(0)的边,这时候我们想起(SPFA)中有一种叫双端队列优化的东西,那么我们只需将其稍作修改,通往目前点的边权若为(0)则将其放在前端,否则放在后端,这样就保证了每个点的进队数量尽量少,并且可以保证第一次搜到终点时其答案就是最小的,可以直接退出。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=500+3;
    int head[maxn*maxn],tot,n,m,dis[maxn*maxn];
    struct edge{
    	int to,next,w;
    }e[maxn*maxn*4];//一定注意边的数量!!!
    void add(int a,int b,int w){
    	e[++tot].to=b;
    	e[tot].w=w;
    	e[tot].next=head[a];
    	head[a]=tot;
    }
    void spfa(){
    	deque<int> q;
    	memset(dis,0x3f,sizeof(dis));
    	dis[1]=0;
    	q.push_front(1);
    	while(!q.empty()){
    		int u=q.front();
    		q.pop_front();
    		for(int i=head[u];i;i=e[i].next){
    			int v=e[i].to;
    			if(dis[u]+e[i].w<dis[v]){
    				dis[v]=dis[u]+e[i].w;
    				if(v==(n+1)*(m+1)) return;
    				if(!e[i].w) q.push_front(v);
    				else q.push_back(v);
    			}
    		}
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			char tmp;
    			scanf(" %c",&tmp);
    			if(tmp=='/'){
    				add((i-1)*(m+1)+j+1,i*(m+1)+j,0);
    				add(i*(m+1)+j,(i-1)*(m+1)+j+1,0);
    				add((i-1)*(m+1)+j,i*(m+1)+j+1,1);
    				add(i*(m+1)+j+1,(i-1)*(m+1)+j,1);
    			}
    			else{
    				add((i-1)*(m+1)+j+1,i*(m+1)+j,1);
    				add(i*(m+1)+j,(i-1)*(m+1)+j+1,1);
    				add((i-1)*(m+1)+j,i*(m+1)+j+1,0);
    				add(i*(m+1)+j+1,(i-1)*(m+1)+j,0);
    			}
    		}
    	}
    	spfa();
    	if(dis[(n+1)*(m+1)]==0x3f3f3f3f) printf("NO SOLUTION
    ");
    	else printf("%d
    ",dis[(n+1)*(m+1)]);
    	return 0;
    }
    

    幸甚至哉,歌以咏志。

  • 相关阅读:
    Http学习(一)
    Android Studio 创建aar包与引用
    C语言模块化编译介绍
    程序结构和分支语句介绍
    数据类型、常量、变量、printf、scanf和运算符
    第一个C语言程序
    Xcode相关整理
    Java: IO 学习小结
    Java: RandomAccessFile
    Java: IO 字符流
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/13418897.html
Copyright © 2011-2022 走看看