Party Lamps

题意:有N盏灯,编号为(1~N)。有四个开关,功能分别为(改变全部灯的状态,改变奇数灯的状态,改变偶数灯的状态,改变3k+1(k>=0)灯的状态)。给定一个按键的次数C还有某些灯的状态,如果开始的时候所有灯都是亮的,求解最后可能的状态

解题思路

  1. 读入输入
  2. 每个开关按两次相当于没按,所以每个按键只有可能是按下或者没按,那么最后按键的状态只有2^4 = 16种,将这16种状态列出来可以得到最后所有可能的等的状态
  3. 如果某种按键情况下按下了N枚按键,那么如果C = N + 2k (k>=0),则C次按键最终可以得到这样的按键情况
  4. 从输入中获得的C可以得到最终可能的按键情况,然后按照按键条件可以得到最终灯的情况,将这些情况排序一下就能输出最后的结果 

代码

/*
ID: zc.rene1
LANG: C
PROG: lamps
 */


#include<stdio.h>
#include<stdlib.h>
#include<string.h>




enum Button{Button1=1, Button2=2, Button3=4, Button4=8};
int N;


void PrintArray(int *arr, FILE *fout)
{
    int i;
    for (i=0; i<N; i++)
    {
	fprintf(fout, "%d", arr[i]);
    }
    fprintf(fout, "\n");
}


int Bigger(int *arr1, int *arr2)
{
    int i;
    for (i=0; i<N; i++)
    {
	if (arr1[i] > arr2[i])
	{
	    return 1;
	}
	else if (arr1[i] < arr2[i])
	{
	    return 0;
	}
	else
	{
	    continue;
	}
    }
    return 1;
}


void SortArray(int **arr, int index)
{
    int i, j;
    int *temp;
    for (i=index-1; i>0; i--)
    {
	for (j=0; j<i; j++)
	{
	    if (Bigger(arr[j], arr[j+1]))
	    {
		temp = arr[j];
		arr[j] = arr[j+1];
		arr[j+1] = temp;
	    }
	}
    }
}
int Check(int *arr, int *final_arr)
{
    int i;
    for (i=0; i<N; i++)
    {
	if ((final_arr[i] != -1) && (arr[i] != final_arr[i]))
	{
	    return 0;
	}
    }
    return 1;
}


int Count(int num)
{
    int ret = 0;


    while (num != 0)
    {
	if (num%2 == 1)
	{
	    ret++;
	}
	num >>= 1;
    }


    return ret;
}


void GenerateState(int button, int* arr)
{
    int i;
    if ((button&Button1) != 0)
    {
	for (i=0; i<N; i++)
	{
	    arr[i] = ((arr[i]==0)?1:0);
	}
    }
    if ((button&Button2) != 0)
    {
	for (i=0; i<N; i+=2)
	{
	    arr[i] = ((arr[i]==0)?1:0);
	}
    }
    if ((button&Button3) != 0)
    {
	for (i=1; i<N; i+=2)
	{
	    arr[i] = ((arr[i]==0)?1:0);
	}
    }
    if ((button&Button4) != 0)
    {
	for (i=0; i<N; i+=3)
	{
	    arr[i] = ((arr[i]==0)?1:0);
	}
    }
} 






int main(void)
{
    FILE *fin, *fout;
    int **state;
    int *final_state;
    int **result;
    int C;
    int i, j, index, temp;
    fin = fopen("lamps.in", "r");
    fout = fopen("lamps.out", "w");


    fscanf(fin, "%d\n%d", &N, &C);
    final_state = (int*)malloc(N*sizeof(int));
    memset(final_state, -1, N*sizeof(int));
    state = (int**)malloc(16*sizeof(int*));
    result = (int**)malloc(16*sizeof(int*));


    for (i=0; i<16; i++)
    {
	state[i] = (int*)malloc(N*sizeof(int));
	for (j=0; j<N; j++)
	{
	    state[i][j] = 1;
	}
    }


    while (fscanf(fin, "%d", &temp))
    {
	if (temp == -1)
	{
	    break;
	}
	final_state[temp-1] = 1;
    }


    while (fscanf(fin, "%d", &temp))
    {
	if (temp == -1)
	{
	    break;
	}
	final_state[temp-1] = 0;
    }


    for (i=0; i<16; i++)
    {
	GenerateState(i, state[i]);
    }


    index = 0;
    for (i=0; i<16; i++)
    {
	temp = C - Count(i);
	if ((temp>=0)&&(temp%2==0))
	{
	    if (Check(state[i], final_state))
	    {
		result[index++] = state[i];
	    }
	}
    }


    if (index == 0)
    {
	fprintf(fout, "IMPOSSIBLE\n");
    }
    else{
	SortArray(result, index);
	for (i=0; i<index; i++)
	{
	    PrintArray(result[i], fout);
	}
    }


    return 0;
}



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值