USACO :Party Lamps解题报告

来源:互联网 发布:sql rowguid 编辑:程序博客网 时间:2024/06/09 18:00

暴搜必定超时,这道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;
}

原创粉丝点击