这个题开始愣是没整明白他到底是要表述一个什么意思, 到底是刚好在第C次还是<=C次使得灯的状态跟题目的状态相同,最后经过苦苦挣扎我觉得应该是<=C 次。
此题总共有四种按键的情况,给个开关有按与不按两种选择,虽然此题最多有100盏灯,但是仔细观察会发现这些灯是每六个一循环的,所有总共有2^6=64种情况,所以只要判断前六个灯的情况就可以了。
之前我说过后面的题还会用到位运算,那么此题我们同样用位运算来模拟灯的状态,0表示关,1表示开。
对于四种操作:
操作1:异或(111111)2=63
操作2:异或(010101)2=21
操作3:异或(101010)2=42
操作4:异或(100100)2=36
判断状态是否符合题意,则可以用&和|完成:
先将题目给出的灯的状态映射到1~6之间,即(灯的编号)%6
生成一个6位二进制数isOn,其中题目给出是ON的灯的对应位为1,其余为0
生成一个6位二进制数isOff,其中题目给出是OFF的灯的对应位为0,其余为1
若当前状态state满足:
(state&isOn)==isOn && (state|isOff)==isOff
则state满足题目要求。
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int n,c;
int change[]={0,63,21,42,36,0};//四种操作
bool ON[100],OFF[100],ans[100];
bool FIND=false;
bool ok(int a)
{
for(int i=1;i<=6;i++)
if(ON[i] && !((a>>(6-i)&1))||OFF[i] && (a>>(6-i)&1))
return false;
return true;
}
void dfs(int state,int deep,int cnt)
{
int temp=state;
if(deep>5)return;
if(cnt<=c&&ok(state))
{
ans[state]=true;
FIND=true;
}
state=state^change[deep];
dfs(state,deep+1,cnt+1);//按下
dfs(temp,deep+1,cnt);//没按下
}
void out(int x)
{
int cnt=0;
while(cnt<n)
{
for(int i=5;i>=0;i--)
{
int temp=(x>>i)&1;
x>>1;
cout<<temp;
cnt++;
if(cnt==n)
break;
}
}
cout<<endl;
}
int main()
{
freopen("lamps.in","r",stdin);
freopen("lamps.out","w",stdout);
int k;
memset(ON,0,sizeof(ON));
memset(OFF,0,sizeof(OFF));
memset(ans,0,sizeof(ans));
cin>>n>>c;
while (cin>>k)
{
if (k==-1)
break;
k%=6;
if(k==0) k=6;
ON[k]=true;
}
while (cin>>k)
{
if (k==-1)
break;
k%=6;
if (k==0) k=6;
OFF[k]=true;
}
dfs(63,1,0);
if(!FIND)
cout<<"IMPOSSIBLE"<<endl;
else
for(int i=0;i<=63;i++)
if(ans[i])
out(i);
fclose(stdin);
fclose(stdout);
return 0;
}