暴搜必定超时,这道IOI的题有两个优化技巧:
1.根据4个开关的特性,每隔6盏灯状态必定是一样的。因此只需考虑前6盏灯即可。
2.由于每个开关按奇数次等于按一次,按偶数次等于没按。因此每个开关只需考虑按或者没按两种状态。4个开关共枚举16种情况即可。
两个判断是否得解的条件:1.枚举按开关的次数必须大于给出按的开关总次数C,且奇偶性相同(仔细想想就知道怎么回事) 2.与给出的一些灯的状态匹配
/*
ID: xpli1
PROG: lamps
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define OUT fout
#define IN fin
ofstream fout ("lamps.out");
ifstream fin ("lamps.in");
int N,C;
int s;
int t;
int btn[4] = {1,2,4,8};
vector<int> res;
bool po;
void output(){
sort(res.begin(),res.end());
int sz = res.size();
int i,j,val,cnt;
int index[7] = {0};
for(i=0; i<sz; i++){
val = res[i];
for(j=1; j<7; j++)
index[j] = val&(1<<(6-j))? 1:0;
cnt = 0;
while(cnt<N){
for(j=1; j<7; j++){
cnt++;
OUT << index[j];
if(cnt==N) break;
}
}
OUT << endl;
}
}
int main()
{
IN >> N >> C;
int state;
int index[7] = {0};
while(IN >> state, state != -1){
state %= 6;
if(state==0) state = 6;
s |= (1<<(6-state));
index[state] = 1;
}
while(IN >> state, state != -1){
state %= 6;
if(state==0) state = 6;
index[state] = 1;
}
int i,j,cnt;
po = false;
for(i=0; i<16; i++){
cnt = 0;
t = (1<<6)-1;
if(btn[0]&i){
cnt++;
t ^=(1<<6)-1;
}
if(btn[1]&i){
cnt++;
t ^= 21;
}
if(btn[2]&i){
cnt++;
t ^= (21<<1);
}
if(btn[3]&i){
cnt++;
t ^= (9<<2);
}
if(cnt>C) continue;
if((cnt&1) != (C&1)) continue;
for(j=1; j<7; j++){
if(index[j]!=0 && (t&(1<<(6-j)))!=(s&(1<<(6-j)))) break;
}
if(j==7) {po=true;res.push_back(t);}
}
if(po == false)
OUT << "IMPOSSIBLE"<<endl;
else
output();
return 0;
}