搜索—Switch the lamp on

[BalticOI 2011 Day1] Switch the Lamp On

题面翻译

题目描述

Casper 正在设计电路。有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会。有 \(N\times M\) 个这样的元件,你想将其排列成 \(N\) 行,每行 \(M\) 个。 电源连接到板的左上角。灯连接到板的右下角。只有在电源和灯之间有一条电线连接的情况下,灯才会亮着。为了打开灯,任何数量的电路元件都可以转动 90°(两个方向)。

在上面的图片中,灯是关着的。如果右边的第二列的任何一个电路元件被旋转 90°,电源和灯都会连接,灯被打开。现在请你编写一个程序,求出最小需要多少旋转多少电路元件。

输入输出格式

输入格式

输入的第一行包含两个整数 \(N\)\(M\),表示盘子的尺寸。 在以下 \(N\) 行中,每一行有 \(M\) 个符号 \/,表示连接对应电路元件对角线的导线的方向。

输出格式:

如果可以打开灯,那么输出只包含一个整数,表示最少转动电路元件的数量。

如果不可能打开灯,输出 NO SOLUTION

题目描述

Casper is designing an electronic circuit on a \(N \times M\) rectangular grid plate. There are \(N \times M\) square tiles that are aligned to the grid on the plate. Two (out of four) opposite corners of each tile are connected by a wire.

A power source is connected to the top left corner of the plate. A lamp is connected to the bottom right corner of the plate. The lamp is on only if there is a path of wires connecting power source to lamp. In order to switch the lamp on, any number of tiles can be turned by 90° (in both directions).

0

In the picture above the lamp is off. If any one of the tiles in the second column from the right is turned by 90° , power source and lamp get connected, and the lamp is on.

Write a program to find out the minimal number of tiles that have to be turned by 90° to switch the lamp on.

输入格式

The first line of input contains two integer numbers \(N\) and \(M\), the dimensions of the plate. In each of the following \(N\) lines there are \(M\) symbols – either \ or / – which indicate the direction of the wire connecting the opposite vertices of the corresponding tile.

输出格式

There must be exactly one line of output. If it is possible to switch the lamp on, this line must contain only one integer number: the minimal number of tiles that have to be turned to switch on the lamp. If it is not possible, output the string: NO SOLUTION

样例 #1

样例输入 #1

3 5
\\/\\
\\///
/\\\\

样例输出 #1

1

提示

对于 \(40\%\) 的数据,\(1 \le N \le 4\)\(1 \le M \le 5\)

对于所有数据,\(1 \le N,M \le 500\)

分析

建模为最短路径问题,把边权看做0,1;需要旋转就是1否则就是0。这里选择用bfs+双端队列去实现。双端队列可以把优先队列的排序操作复杂度降为O(1),因为我们只需要将0插入队头,1插入队尾。
这道题需要点图与格图一起使用,下面代码点从(1,1)开始,格子从1,1开始。

代码实现

#include <bits/stdc++.h>
using namespace std;
const int dir[4][2] = {-1,-1,-1,1,1,-1,1,1}; //根据题目电路原件活动范围类似"X",表示点的移动方向
const int ab[4] = {2,1,1,2};//元件可能有两个方向,即 / 或 \。分别用1,2表示
const int cd[4][2] = {-1,-1,-1,0,0,-1,0,0};//表示格子的移动方向
int graph[505][505],dis[505][505];
struct P
{
	int x,y,dis;
};
int read_ch(){
	char c;
	while((c = getchar())!='/'&&c!='\\');//这里//表示的就是/,因为/是转义符
	return c== '/' ?1:2;
}
void bfs(int n,int m){
	deque<P>dq;
	dq.push_back((P){1,1,0});
	dis[1][1] = 0;
	while(!dq.empty()){
		P u = dq.front();
		dq.pop_front();
		for(int i = 0;i<4;++i){
			int nx = u.x + dir[i][0];
			int ny = u.y + dir[i][1];//移动到了周围的点
			int d=graph[u.x+cd[i][0]][u.y+cd[i][1]]!=ab[i];//检查周围的格子与实际格子里的元器件是否一样
			if(nx>0&&ny>0&&nx<=n+1&& ny <=m+1 && dis[nx][ny] > dis[u.x][u.y] + d){ //    如果一个结点再次进队,那么距离应该更小。实际上,
                //由于再次进队时,距离肯定更大,所以这里的作用是阻止再次入队

				 dis[nx][ny] = dis[u.x][u.y] + d;
                if (d == 0) {//边权=0,插到队头   
                    dq.push_front((P){nx, ny, dis[nx][ny]});
                } else {//边权=1,插到队尾
                    dq.push_back((P){nx, ny, dis[nx][ny]});
                }
				 if (nx == n+1 && ny == m+1) {//到终点退出。
                    return;
			}
		}
	}
}
}
int main(){
int n, m;
    cin >> n >> m;
    
    memset(dis, 0x3f, sizeof(dis));
    
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            graph[i][j] = read_ch();
        }
    }
    
    bfs(n, m);
    
    if (dis[n+1][m+1] != 0x3f3f3f3f) {
        cout << dis[n+1][m+1];
    } else {
        cout << "NO SOLUTION";
    }

    
	return 0;
}
posted @ 2023-08-22 20:35  LongDz  阅读(34)  评论(0)    收藏  举报