洛谷 P4667 [BalticOI 2011] Switch the Lamp On (Day1)

题目描述

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

img

img

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

输入格式

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

输出格式

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

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

题意翻译

输入输出样例

输入 #1复制

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

输出 #1复制

1

说明/提示

对于 40% 的数据,1≤N≤4,1≤M≤5。

对于所有数据,1≤N,M≤500。

算法分析

用双端队列做BFS,加上记忆化,可以把不需要转向的电线放在队首,把要转向的电线放在队尾,统一从队首出队,如果搜到了要转向的电线,步数要+1,不转向的不变,直到搜完,最后输出vis_n_m。

坑点

1.搜到要转向的步数记得+1。

2.转向的入队时要push_back。

AC代码

#include<bits/stdc++.h>
using namespace std;
int dx[] = {1,-1,-1,1};
int dy[] = {1,1,-1,-1};
int dx2[] = {0,-1,-1,0};
int dy2[] = {0,0,-1,-1};
char t[] = "\\/\\/";
int n,m;
deque<int> qx,qy;
char a[505][505];
int vis[505][505];
void bfs(){
	for(int i = 0; i<=n; i++){
		for(int j = 0; j<=m; j++){
			vis[i][j] = INT_MAX;
		}
	}
	qx.push_back(0);
	qy.push_back(0);
	vis[0][0] = 0; 
	while(!qx.empty()){
		int x = qx.front();
		int y = qy.front();
		qx.pop_front();
		qy.pop_front();
		for(int i = 0; i<4; i++){
			int xx = x+dx[i];
			int yy = y+dy[i];
			int xx2 = x+dx2[i];
			int yy2 = y+dy2[i];
			if(xx>=0 && xx<=n && yy>=0 && yy<=m){
				if(t[i]!=a[xx2][yy2]){
					int temp = vis[x][y]+1;
					if(temp<vis[xx][yy]){
						qx.push_back(xx);
						qy.push_back(yy);
						vis[xx][yy] = temp; 	
					}
				}else{
					int temp = vis[x][y];
					if(temp<vis[xx][yy]){
						qx.push_front(xx);
						qy.push_front(yy);
						vis[xx][yy] = temp;	
					}
				}
			}
		}
	}
	cout<<vis[n][m];
}
int main(){
	cin>>n>>m; 
	for(int i = 0; i<n; i++){
		cin>>a[i];
	}
	if((n+m)%2==1){
		cout<<"NO SOLUTION";
	}else{
		bfs();
	}
	return 0;		
}
posted @ 2026-05-04 12:27  xmgene  阅读(22)  评论(0)    收藏  举报