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 toN.
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 0110110110In 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.
/*
ID: conicoc1
LANG: C
TASK: lamps
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
FILE *fin,*fout;
int FinalLamps[100];
int NowLamps[100];
int counter,binary;
int N;
int temp=0;
int flag=0;
int Answer[16][100];
void PrintAnswer()
{
int i,j;
for(i=0;i<flag;i++)
{
for(j=0;j<N;j++)
{
if(Answer[i][j])
fprintf(fout,"1");
else
fprintf(fout,"0");
}
fprintf(fout,"\n");
}
}
void Button(int Choose)
{
int i;
switch(Choose)
{
case 1:
for(i=0;i<N;i++)
{
if(NowLamps[i]==0)
NowLamps[i]=1;
else
NowLamps[i]=0;
}break;
case 2:
for(i=1;i<N;i+=2)
{
if(NowLamps[i]==0)
NowLamps[i]=1;
else
NowLamps[i]=0;
}break;
case 3:
for(i=0;i<N;i+=2)
{
if(NowLamps[i]==0)
NowLamps[i]=1;
else
NowLamps[i]=0;
}break;
case 4:
for(i=0;i<N;i+=3)
{
if(NowLamps[i]==0)
NowLamps[i]=1;
else
NowLamps[i]=0;
}break;
}
}
int judge()
{
int i;
for(i=0;i<N;i++)
{
if(FinalLamps[i]!=-1&&FinalLamps[i]!=NowLamps[i])
return 0;
}
return 1;
}
void ToAnswer()
{
int i;
for(i=0;i<N;i++)
{
if(NowLamps[i])
Answer[flag][i]=1;
else
Answer[flag][i]=0;
}
flag++;
}
void Act(int i,int j,int k,int t)
{
if(i==1)
Button(1);
if(j==1)
Button(2);
if(k==1)
Button(3);
if(t==1)
Button(4);
}
void SortAnswer()
{
int temp,i,j,k;
for(i=0;i<flag-1;i++)
{
for(j=0;j<flag-i-1;j++)
{
for(k=0;k<N;k++)
{
if(Answer[j][k]<Answer[j+1][k])
break;
if(Answer[j][k]>Answer[j+1][k])
{
for(k=0;k<N;k++)
{
temp=Answer[j][k];
Answer[j][k]=Answer[j+1][k];
Answer[j+1][k]=temp;
}
break;
}
}
}
}
}
int main()
{
fin=fopen("lamps.in","r");
fout=fopen("lamps.out","w");
memset(FinalLamps,-1,sizeof(FinalLamps));
int i,j,k,t;
fscanf(fin,"%d",&N);
fscanf(fin,"%d",&counter);
do
{
fscanf(fin,"%d",&temp);
if(temp!=-1)
FinalLamps[temp-1]=1;
}
while(temp!=-1);
do
{
fscanf(fin,"%d",&temp);
if(temp!=-1)
FinalLamps[temp-1]=0;
}
while(temp!=-1);
for(i=0;i<N;i++)
{
NowLamps[i]=1;
}
//读入数据完毕
for(i=0;i<=1;i++)
{
for(j=0;j<=1;j++)
{
for(k=0;k<=1;k++)
{
for(t=0;t<=1;t++)
{
if(counter<3)
{
if(counter==i+j+k+t||counter%2==i+j+k+t)
{
Act(i,j,k,t);
if(judge())
ToAnswer();
Act(i,j,k,t);
}
}
else
if(counter%2==(i+j+k+t)%2)
{
// printf("%d %d %d %d %d\n",i,j,k,t,flag);
Act(i,j,k,t);
if(judge())
ToAnswer();
Act(i,j,k,t);
}
}
}
}
}
if(flag==0)
fprintf(fout,"IMPOSSIBLE\n");
else
{
SortAnswer();
PrintAnswer();
}
return 0;
}
代码有点长
下面是analysis的位运算方法:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAXLAMP 6
#define LAMPMASK ((1<<MAXLAMP)-1)
int nlamp;
int nswitch;
int ison;
int known;
int poss[1<<MAXLAMP];
int flip[4] = {
LAMPMASK, /* flip all lights */
LAMPMASK & 0xAA, /* flip odd lights */
LAMPMASK & 0x55, /* flip even lights */
LAMPMASK & ((1<<(MAXLAMP-1))|(1<<(MAXLAMP-4))) /* lights 1, 4 */
};
/*
* Starting with current light state ``lights'', flip exactly n switches
* with number >= i.
*/
void
search(int lights, int i, int n)
{
if(n == 0) {
if((lights & known) == ison)
poss[lights] = 1;
return;
}
for(; i<4; i++)
search(lights ^ flip[i], i+1, n-1);
}
void
printseq(FILE *fout, int lights)
{
int i;
char s[100+1];
for(i=0; i<nlamp; i++)
s[i] = (lights & (1<<(MAXLAMP-1 - i%MAXLAMP))) ? '1' : '0';
s[nlamp] = '\0';
fprintf(fout, "%s\n", s);
}
void
main(void)
{
FILE *fin, *fout;
int a, i, impossible;
fin = fopen("lamps.in", "r");
fout = fopen("lamps.out", "w");
assert(fin != NULL && fout != NULL);
fscanf(fin, "%d %d", &nlamp, &nswitch);
for(;;) {
fscanf(fin, "%d", &a);
if(a == -1)
break;
a = MAXLAMP-1 - (a-1) % MAXLAMP;
ison |= 1<<a;
known |= 1<<a;
}
for(;;) {
fscanf(fin, "%d", &a);
if(a == -1)
break;
a = MAXLAMP-1 - (a-1) % MAXLAMP;
assert((ison & (1<<a)) == 0);
known |= 1<<a;
}
if(nswitch > 4)
if(nswitch%2 == 0)
nswitch = 4;
else
nswitch = 3;
for(; nswitch >= 0; nswitch -= 2)
search(LAMPMASK, 0, nswitch);
impossible = 1;
for(i=0; i<(1<<MAXLAMP); i++) {
if(poss[i]) {
printseq(fout, i);
impossible = 0;
}
}
if(impossible)
fprintf(fout, "IMPOSSIBLE\n");
exit(0);
}