题解:P10449 费解的开关
P10449 费解的开关
暴力深搜
( 816ms / 564.00KB / 1011B C++98 O2)
优点:
- 能过。
- ......
故曰 : 仅作为一种新思路供参考。
思路:找到图中为
部分难点:
- 偏移数组(又称方向数组):通常意味着你有一个指针指向一个数组,并且你想要根据某个偏移量来访问数组中的元素。这可以通过使用指针算术来实现。
(剩余解析请见注释)
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,s,px[5]={0,-1,0,1,0},py[5]={0,0,1,0,-1};//n 为 n 个待解决的游戏初始状态,
// s 记录每个状态中,遍历到不同的点时最少步数, px 和 py 是偏移数组(见上)。
bool g[10][10],an;//g是geography,即游戏初始状态;an判断是否有answer。
string a;//用来输入。
int check(){//判断整张图是否都为 1 , 至于为什么是 int , 请看下面的返回值的注释 。
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
if(!g[i][j]) return i;//返回出现 0 的行数 ,减少运算 。
return 0;//表示整张图都为 1 。
}
void oper(int a,int b){//操作 ( operate的简写 ) , 改变坐标为(a,b) 的点及四周的点的状态。
for(int i=0;i<=4;i++)
g[a+px[i]][b+py[i]]=!g[a+px[i]][b+py[i]];
}
void su(int a){//深搜第 a 步。
if(a>7) return;//步数过多,直接排除。
int x=check(),y;//x 行 y 列,即该步改变状态的点的坐标。
if(!x){//此时整张图都为 1 。
s=min(s,a);//每次整张图都为 1 时最小的步数。
an=1;//已有 answer !!
return;
}
for(int i=1;i<=5;i++)//寻找此时图中状态为 0 的点。
if(!g[x][i]){// x 已在定义的时候找出了。
y=i;//定位到此时状态为 0 的点。
break;
}
for(int i=0;i<=4;i++){//列举包括自己共 5 个点 , 一一搜索一遍。
int x2=x+px[i],y2=y+py[i];//确定点的坐标。
if(x2<1 || x2>5 || y2<1 || y2>5) continue;//找到的点不在图中,无法改变
//状态。
oper(x2,y2);//改变该点的状态。
su(a+1);//继续深搜修改过后的图。
oper(x2,y2);//状态还原,为了不影响以后的遍历。
}
}
int main(){
cin>>n;
while(n--){
s=10;// 初始为较大值(大于 6 即可)。
an=0;// 初始无 answer(答案)。
for(int i=1;i<=5;i++){// 输入。
cin>>a;
for(int j=1;j<=5;j++) g[i][j]=a[j-1]-'0';
}
su(1);// 从第 1 个操作开始。
if(an) cout<<s-1<<endl;// 有答案。
else cout<<-1<<endl;// 无答案输出 -1 。
}
return 0;
}