USACO SECTION 2.2 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 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
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.

/*
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);
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值