zoukankan      html  css  js  c++  java
  • 【YBTOJ】【Luogu P4667】[BalticOI 2011 Day1]Switch the Lamp On

    链接:

    题目

    题目大意:

    在一个 (n imes m) 的网格图中:

    如果当前格子是 ,则可以让格子左上和右下的点连接,/ 则相反。但如果格子是 / 还要让左上和右下的点连接,就要增加 (1) 个价值。问从 ((1,1))((n+1,m+1)) 的最少价值是多少,无解则输出 NO SOLUTION

    正文:

    先考虑无解的情况。如果当前在 ((1,1)),不能到达的点有:

    相当于,一个点 ((x,y)),如果 (x+y) 是奇数,那就到不了,直接输出无解。


    剩下的就简单了,能够直接走的就相当于边权为 (0),否则为 (1),跑个最短路就过了。

    但是,数据太大不能直接 SPFA,考虑用双端队列来做。因为是 BFS,一个点第一次出队就是最短的,那么如果有边权为零的,就让它优先出队(即从头放入队列),否则正常。

    代码:

    const int N = 510;
    
    struct node
    {
    	int z, to, next;
    }e[N * N * 4];
    int n, m, tot;
    int dis[N * N], head[N * N];
    deque <int> que;
    
    void Add(int x, int y, int z)
    {
    	e[++tot] = (node){z, y, head[x]}, head[x] = tot;
    }
    
    void SPFA(int s)
    {
    	memset(dis, 60, sizeof(dis));
    	for(; !que.empty(); que.pop_front());
    	dis[s] = 0;
    	que.push_back(s);
    	for (; !que.empty(); )
    	{
    		int u = que.front();
    		que.pop_front();
    		for (int i = head[u]; i; i = e[i].next)
    		{
    			int v = e[i].to;
    			if(dis[v] > dis[u] + e[i].z)
    			{
    				dis[v] = dis[u] + e[i].z;
    				if (v == (n + 1) * (m + 1)) return;
    				if(!e[i].z) que.push_front(v);
    				else que.push_back(v);
    			}
    		}
    	}
    }
    
    int id(int x, int y) {return x * (m + 1) + y;} 
    char a[N][N];
    
    int main()
    {
    	int t;
    	for (scanf ("%d", &t); t--; )
    	{
    		memset (dis, 0, sizeof dis);
    		memset (e, 0, sizeof e);
    		memset (head, 0, sizeof head);
    		tot = 0;
    		scanf("%d%d", &n, &m);
    		for(int i = 1; i <= n; i++)
    		{
    			scanf ("%s", a[i] + 1);
    			for (int j = 1; j <= m; j++)
    				if(a[i][j] == '/')
    					Add(id(i, j), id(i - 1, j + 1), 0),
    					Add(id(i - 1, j + 1), id(i, j), 0),
    					Add(id(i - 1, j), id(i, j + 1), 1),
    					Add(id(i, j + 1), id(i - 1, j), 1);
    				else
    					Add(id(i, j), id(i - 1, j + 1), 1),
    					Add(id(i - 1, j + 1), id(i, j), 1),
    					Add(id(i - 1, j), id(i, j + 1), 0),
    					Add(id(i, j + 1), id(i - 1, j), 0);
    		}
    		if ((n + m) % 2) {puts("NO SOLUTION");continue;} 
    		SPFA(1);
    		printf("%d
    ", dis[(n + 1) * (m + 1)]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    洛谷P1120信息奥赛一本通1442 小木棍
    洛谷P1378 油滴扩展
    洛谷P1156 垃圾陷阱
    mybatis-Plus 实践篇之逆向工程
    Interceptor的使用及探究
    mysql,oracle,sqlServer 元数据查询
    navicat premium15免费版安装说明(附工具)
    打印日志你真的会吗?
    线程基础知识-必知必会
    空间复杂度&时间复杂度
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14311416.html
Copyright © 2011-2022 走看看