分析
刚开始的时候,不知道从什么地方对这道题下手,就看了y总的代码,现在算是明白了。
y总的解法就是,从第一排开始改变灯的状态,第一排的状态确定了,后面四排也就确定了。
第一排有五个灯,所以有六种改变状态的方式
第一种改变零个灯的状态,根据排列组合有一种情况。
第二种改变一个灯的状态,根据排列组合有五种情况。
第三种改变两个灯的状态,根据排列组合有十种情况。
第四种改变三个灯的状态,根据排列组合有十种情况。
第五种改变四个灯的状态,根据排列组合有五种情况。
第六种改变五个灯的状态,根据排列组合有一种情况。
合计:三十二种情况。
用1表示改变这个灯的状态,0表示不改变
这样每种情况都对应一个01序列
比如上面的改变0个灯的状态只有一种情况,对应的序列就是00000
这个表达的意思第一排的五个灯不进行任何操作。
10000,就是只改变第一个灯的状态。
然后在这里y总提供一个简便方法:
每个01序列对应一个十进制数,设这个数为 x
要判断这个01序列y位置是不是1可以用这个式子
x >> y & 1 如果y位置是1的话,这个式子的结果就为1.
for(int op = 0; op < 32; op ++ )
{
memcpy(bk,st,sizeof st);
int step = 0;
for(int i = 0;i < 5; i ++ )
{
if(op >> i & 1)
{
step ++ ;
turn(0,i);
}
}
这样这段代码就可以把前面提到的所有情况都遍历一遍。
for(int i = 0;i < 5; i ++ )
{
if(op >> i & 1)
{
step ++ ;
turn(0,i);
}
}
这里的作用:
比如 op 是 11000
前面提到了1是改变状态,通过上面这段代码,就改变了第一排前两个灯的状态,turn的作用就不说了。
改变状态可以是 灯由关变成打开,也可以是从打开变成关闭。
C++ 代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 6;
char bk[N][N], st[N][N];
int n;
int dx[] = {1,0,-1,0,0}, dy[] = {0,1,0,-1,0};
void turn(int x, int y)
{
for(int i = 0; i < 5 ; i ++ )
{
int a = x + dx[i],b = y + dy[i];
if(a < 0 || b < 0 || b > 5 || a > 5 ) continue;
st[a][b]^=1;
}
}
int main()
{
cin >> n;
while(n--)
{
int res = 10;
for(int i = 0; i < 5 ; i ++ ) cin >> st[i];
for(int op = 0; op < 32; op ++ )
{
memcpy(bk,st,sizeof st);
int step = 0;
for(int i = 0;i < 5; i ++ )
{
if(op >> i & 1)
{
step ++ ;
turn(0,i);
}
}
for(int i = 0; i < 4; i ++ )
for(int j = 0; j < 5 ; j ++ )
{
if(st[i][j] == '0')
{
step ++ ;
turn(i+1,j);
}
}
bool it = false;
for(int i = 0; i < 5; i ++ )
{
if(st[4][i]=='0')
{
it = true;
break;
}
}
if(!it)res = min(res,step);
memcpy(st,bk,sizeof bk);
}
if(res > 6) cout << -1 << endl;
else cout << res << endl;
}
return 0;
}
python 代码
T = int(input())
dx,dy = [0,1,0,-1,0],[1,0,-1,0,0]
def doit(f,x,y):
for i in range(5):
xx,yy = x + dx[i],y + dy[i]
if xx < 0 or xx >= 5 or yy < 0 or yy >= 5:continue
if f[xx][yy] == '0':
f[xx][yy] = '1'
else:
f[xx][yy] = '0'
for i in range(T):
lis = []
for j in range(5):
lis.append(list(input()))
res = 10
for j in range(32):
lis2 = []
for ii in range(5):lis2.append(lis[ii][:])
ans = 0
its = True
for k in range(5):
if (j >> k) & 1:
ans += 1
doit(lis2,0,k)
for k in range(4):
for wk in range(5):
if lis2[k][wk] == '0':
doit(lis2,k+1,wk)
ans += 1
for wk in range(5):
if lis2[4][wk] == '0':
its = False
break
if its and res > ans:
res = ans
if res <= 6:
print(res)
else:
print(-1)
if i != T -1:
ttt = input()
赞,刚开始一直没明白枚举第一行的的意思,懂了