1. 灯每6个一组状态循环一次:
==> 只需要枚举灯"1,2,3,4,5,6即可",之后的状态在输出时按要求循环输出即可。
2. 异或操作 作为 状态转移函数可以大大减少状态枚举的搜索树深度:
——异或满足“交换律(已证-真值表)”和“结合律(已证-真值表)”;偶数次异或操作将不对状态产生任何影响。
==> 只需要考虑每种灯被按下0次/1次的所有组合情况即可
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
int n,c,t;
bool f[101]; //初始状态 11...11
bool g[101]; //当前状态
int last[101]; //最终状态限制 (-1没有指定;1 ON;0 OFF)
bool judge()
{
for(int i=1; i<=n; i++)
if(last[i]!=-1&&last[i]!=g[i])
return false;
return true;
}
void turn1()
{
for(int i=1; i<=n; i++)
g[i]=!g[i];
}
void turn2()
{
for(int i=1; i<=n; i+=2)
g[i]=!g[i];
}
void turn3()
{
for(int i=2; i<=n;i+=2)
g[i]=!g[i];
}
void turn4()
{
for(int i=0,k=1; k<=n;)
{
g[k]=!g[k];
i++;
k=3*i+1;
}
}
int main()
{
cin>>n;
cin>>c;
vector<string> vec;
string s;
for(int i=1; i<=n; i++)f[i]=1;
for(int i=1; i<=n; i++)last[i]=-1;
while(cin>>t&&t!=-1)
last[t]=1;
while(cin>>t&&t!=-1)
last[t]=0;
//枚举状态
int i1, i2, i3, i4,i;
for(i1=0; i1<=1; i1++)
for(i2=0; i2<=1; i2++)
for(i3=0; i3<=1; i3++)
for(i4=0; i4<=1; i4++){
if( c>=(i1+i2+i3+i4) &&(c-(i1+i2+i3+i4))%2==0) //c-(i1+i2+i3+i4))%2==0 ==>最终翻转次数必须为c
{
for(i=1; i<=n;i++)
g[i]=f[i];
if(i1)turn1();
if(i2)turn2();
if(i3)turn3();
if(i4)turn4();
if(judge()){
//1. 数字i转为对应字符'i' i.e. 1 --> '1' ('1'='0'+1)
//2. string s="";
// (1)可以追加字符串: s+="blabla";
// (2)可以追加字符:s+='b';
for(s="",i=1; i<=n; i++)
s+='0'+g[i];
vec.push_back(s);
}
}
}
//对vector<string>vec 进行sort(...)可以保证元素按照字典序进行排列
sort(vec.begin(),vec.end());
if(vec.size()==0)cout<<"IMPOSSIBLE"<<endl;
else{
for(i=0; i<vec.size(); i++)
cout<<vec[i]<<endl;
}
system("pause");
return 0;
}