P1468 [USACO2.2] 派对灯 Party Lamps

题目描述

在 IOI98 的节日宴会上,我们有 n 盏彩色灯,他们分别从1∼n 被标上号码。这些灯都连接到四个按钮:

按钮 1:当按下此按钮,将改变所有的灯:本来亮着的灯就熄灭,本来是关着的灯被点亮。

按钮 2:当按下此按钮,将改变所有奇数号的灯。

按钮 3:当按下此按钮,将改变所有偶数号的灯。

按钮 4:当按下此按钮,将改变所有序号是3k+1 (k∈[0,+∞)∩Z) 的灯。例如:1,4,7,10…

一个计数器 c 记录按钮被按下的次数。当宴会开始,所有的灯都亮着,此时计数器 c 为 0。

你将得到计数器 c 上的数值和经过若干操作后某些灯的状态。写一个程序去找出所有灯最后可能的与所给出信息相符的状态,并且没有重复。

输入格式

第一行一个正整数 n;第二行一个整数 c,表示最后计数器的数值。
第三行若干个整数,表示最后亮着的灯,以 -1 结束。
第四行若干个整数,表示最后关着的灯,以 -1 结束。

保证不会有灯会在输入中出现两次。

输出格式

每一行是所有灯可能的最后状态(没有重复)。
每一行有 n 个字符,第 i 个字符表示 i 号灯。0 表示关闭,1 表示亮着。这些行必须从小到大排列(看作是二进制数)。

如果没有可能的状态,则输出一行 IMPOSSIBLE

输入输出样例

输入 #1

10
1
-1
7 -1

输出 #1

0000000000
0101010101
0110110110

说明/提示

【数据范围】
对于 100% 的数据,10≤n≤100,0≤c≤104。

【样例解释】
在这个样例中,有三种可能的状态:

  • 所有灯都关着

  • 1,4,7,10 号灯关着,2,3,5,6,8,9 亮着。

  • 1,3,5,7,9 号灯关着,2,4,6,8,10 亮着。

翻译来自NOCOW

USACO 2.2

#include<bits/stdc++.h>
using namespace std;
//每6个灯的状态都是一样的,故只需记录前6盏灯的情况 
char lamp[10][10]={
        {"111111"},    //按过(1,2,3)  次数:0次,3次 
        {"011011"},    //按过(1,2,3,4),(4)  次数:4次,1次
	    {"101010"},    //按过(1,2),(3)  次数:2次,1次
	    {"010101"},    //按过(2),(1,3)  次数:1次,2次
	    {"001110"},    //按过(1,2,4),(3,4)  次数:3次,2次
	    {"110001"},    //按过(1,3,4),(2,4)  次数:3次,2次 
	    {"100100"},    //按过(1,4),(2,3,4)  次数:2次,3次
	    {"000000"},	   //按过(1),(2,3)  次数:1次,2次
	};
int num[10][10]={{0,3},{1,4},{1,2},{1,2},{2,3},{2,3},{2,3},{1,2}};    //对应的不同按钮的次数 
int lon[10]={0},loff[10]={0};
int n,c,x;
bool judge(int index){
	for(int i=0;i<7;++i)
	   if((lon[i] && lamp[index][i]=='0') || (loff[i] && lamp[index][i]=='1'))
	      return 0;
	return 1;
}
int main(){
    scanf("%d%d",&n,&c);
    while(1){
    	scanf("%d",&x);
    	if(x==-1) break;
    	lon[(x-1)%6]=1;    //存放亮着的灯,直接对6取余保存 
	}
	while(1){
		scanf("%d",&x);
		if(x==-1) break;
		loff[(x-1)%6]=1;    //存放灭的灯 
	} 
	int cnt=0;
	char ans[10][10];
	if(c<3){
		for(int i=0;i<8;++i)    //第i种操作造成的i种状态
		   for(int j=0;j<=1;++j){    //穷举所有的操作 
		   	  if((num[i][j]==c || num[i][j]==c-2) && judge(i))    //num[i][j]==c-2成立时,只有有效按钮次数为0
				 strcpy(ans[cnt++],lamp[i]);    //将这种可能性保存起来 
		   } 
	} 
	else{
		for(int i=0;i<8;++i)
		   if(judge(i))
		      strcpy(ans[cnt++],lamp[i]);
	}
	if(cnt==0) printf("IMPOSSIBLE\n");
	else{
		for(int i=0;i<cnt-1;++i)    //排序
		   for(int j=0;j<cnt-1-i;++j)
		      if(strcmp(ans[j],ans[j+1])>0){
		      	 char temp[8];
				   strcpy(temp,ans[j]);
				   strcpy(ans[j],ans[j+1]);
				   strcpy(ans[j+1],temp);
			  } 
		for(int i=0;i<cnt;++i){
			for(int j=0;j<n;++j)
			    printf("%c",ans[i][j%6]);
			printf("\n");
		}
	}
    return 0;
} 

  • 41
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值