USACO 2.2.4 Party Lamps


Party Lamps
IOI 98

To brighten up the gala dinner of the IOI'98 we have a set of N (10 <= N <= 100) colored lamps numbered from 1 to N.

The lamps are connected to four buttons:

    Button 1: When this button is pressed, all the lamps change their state: those that are ON are turned OFF and those that are OFF are turned ON.
    Button 2: Changes the state of all the odd numbered lamps.
    Button 3: Changes the state of all the even numbered lamps.
    Button 4: Changes the state of the lamps whose number is of the form 3xK+1 (with K>=0), i.e., 1,4,7,...

A counter C records the total number of button presses.

When the party starts, all the lamps are ON and the counter C is set to zero.

You are given the value of counter C (0 <= C <= 10000) and the final state of some of the lamps after some operations have been executed. Write a program to determine all the possible final configurations of the N lamps that are consistent with the given information, without repetitions.
PROGRAM NAME: lamps
INPUT FORMAT

No lamp will be listed twice in the input.
Line 1:     N
Line 2:     Final value of C
Line 3:     Some lamp numbers ON in the final configuration, separated by one space and terminated by the integer -1.
Line 4:     Some lamp numbers OFF in the final configuration, separated by one space and terminated by the integer -1.
SAMPLE INPUT (file lamps.in)

10
1
-1
7 -1

In this case, there are 10 lamps and only one button has been pressed. Lamp 7 is OFF in the final configuration.
OUTPUT FORMAT

Lines with all the possible final configurations (without repetitions) of all the lamps. Each line has N characters, where the first character represents the state of lamp 1 and the last character represents the state of lamp N. A 0 (zero) stands for a lamp that is OFF, and a 1 (one) stands for a lamp that is ON. The lines must be ordered from least to largest (as binary numbers).

If there are no possible configurations, output a single line with the single word `IMPOSSIBLE'
SAMPLE OUTPUT (file lamps.out)

0000000000
0101010101
0110110110

In this case, there are three possible final configurations:

    All lamps are OFF
    Lamps 1, 4, 7, 10 are OFF and lamps 2, 3, 5, 6, 8, 9 are ON.
    Lamps 1, 3, 5, 7, 9 are OFF and lamps 2, 4, 6, 8, 10 are ON.

题意:题目给出了几种操作灯的方法1代表全部的灯要变化,2代表只变化奇数的灯,3代表只变化偶数的灯,4代表变化3K+1(k>=0)。灯笼数目N,对灯的操作次数C,最后依然亮着的灯,最后灭掉的灯。要求输出最后所有灯可能的情况。

思路:首先,明确一点前六个灯的状态可代表后面所有的灯,也就是说是每六个一循环的。为什么是这样呢?1操作发生变化的循环节为1,2操作和3操作发生变化的循环节是2,4操作发生变化的循环节是3,所以总的灯笼发生变化的循环节是1,2,3的公倍数,就是6了。其次,当输入的C>4时,操作中必定有重复的操作,而同一个操作做两遍其实对于灯来说是没有什么变化的。所以我们可以对灯的操作次数不断的减2,操作次数<=4。明白了这两点解题就容易多了,数据规模缩小了,只要枚举每种可能就可以了。

源代码:

/*
ID: supersnow0622
PROG: test
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <string>
#include<memory.h>
#include<algorithm>
using namespace std;
int on[110],off[110],lamp[7],used[64],start=63,state,N,C,a=0;
string s[300];
void change(int n,int m)
{
 switch (n){
      case 1:state=m xor 63;break;
      case 2:state=m xor 42;break;
      case 3:state=m xor 21;break;
      case 4:state=m xor 36;break;
      }
}
bool convert()
{
    int tempstate=state;
    if(used[tempstate]==1)
     return false;
    used[tempstate]=1;
    int temp[7],num=6;
    memset(temp,0,sizeof(temp));
    while(tempstate!=0)
    {
       temp[num]=tempstate%2;
       if(lamp[num]!=-1&&temp[num]!=lamp[num])
         return false;
       num--;
       tempstate/=2;
    }
    if(lamp[1]!=-1&&lamp[1]!=temp[1])
     return false;
    int m=N/6,n=N%6;
    for(int i=0;i<m;i++)
      for(int j=1;j<7;j++)
        s[a]+=temp[j]+'0';
    for(int i=1;i<=n;i++)
        s[a]+=temp[i]+'0';
    a++;
return true;
}
int main() {
    ofstream fout ("test.out");
    ifstream fin ("test.in");
    int count=0,ok2,ok3,ok4;
    cin>>N>>C;
    while(cin>>on[count]&&on[count]!=-1)
       count++;
    memset(lamp,-1,sizeof(lamp));
    for(int i=0;i<count;i++)
        if(on[i]%6!=0)
         lamp[on[i]%6]=1;
        else lamp[6]=1;
    count=0;
    while(cin>>off[count]&&off[count]!=-1)
       count++;
    if(C==0)
    {
      if(count!=0)
        {cout<<"IMPOSSIBLE"<<endl;return 0;}
      for(int i=0;i<N;i++)
        cout<<"1";
        cout<<endl;
     return 0;
    }
    for(int i=0;i<count;i++)
      if(off[i]%6!=0)
       lamp[off[i]%6]=0;
      else lamp[6]=0;
    while(C>4)
      C=C-2;
    ok2=ok3=ok4=0;
    int judge=0;
    memset(used,0,sizeof(used));
    if(C==2)  ok2=1;
    if(C==3)  ok2=ok3=1;
    if(C==4)  ok2=ok3=ok4=1;
    judge=0;
    for(int i=1;i<=4;i++)
     {
       for(int j=1;ok2==1&&j<=4;j++)
        {
          for(int k=1;ok3==1&&k<=4;k++)
           {
             for(int l=1;ok4==1&&l<=4;l++)
              {
               change(i,start);
               change(j,state);
               change(k,state);
               change(l,state);
               if(convert())  judge++;
              }
              if(ok4==0)
              {
               change(i,start);
               change(j,state);
               change(k,state);
                if(convert())  judge++;
              }
           }
           if(ok3==0)
           {
              change(i,start);
              change(j,state);
              if(convert())  judge++;
           }
        }
         if(ok2==0)
            {
               change(i,start);
               if(convert())  judge++;
            }
    }
    if(!judge)
     cout<<"IMPOSSIBLE"<<endl;
    else {
      sort(s,s+a);
      for(int i=0;i<a;i++)
       cout<<s[i]<<endl;
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值