USACO-Section2.2 Party Lamps【深度优先搜索】

2024-04-12 06:38

本文主要是介绍USACO-Section2.2 Party Lamps【深度优先搜索】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述:

在IOI98的节日宴会上,我们有N(10<=N<=100)盏彩色灯,他们分别从1到N被标上号码。 这些灯都连接到四个按钮:
按钮1:当按下此按钮,将改变所有的灯:本来亮着的灯就熄灭,本来是关着的灯被点亮。
按钮2:当按下此按钮,将改变所有奇数号的灯。
按钮3:当按下此按钮,将改变所有偶数号的灯。
按钮4:当按下此按钮,将改变所有序号是3*K+1(K>=0)的灯。例如:1,4,7…
一个计数器C记录按钮被按下的次数。当宴会开始,所有的灯都亮着,此时计数器C为0。
你将得到计数器C(0<=C<=10000)上的数值和经过若干操作后某些灯的状态。写一个程序去找出所有灯最后可能的与所给出信息相符的状态,并且没有重复。(翻译来源:NOCOW)

INPUT FORMAT:

(file lamps.in)
不会有灯会在输入中出现两次。
第一行: N。
第二行: C最后显示的数值。
第三行: 最后亮着的一些灯,用一个空格分开,以-1为结束。
第四行: 最后关着的一些灯,用一个空格分开,以-1为结束。

OUTPUT FORMAT:

(file lamps.out)
每一行是所有灯可能的最后状态(没有重复)。每一行有N个字符,第1个字符表示1号灯,最后一个字符表示N号灯。0表示关闭,1表示亮着。这些行必须从小到大排列(看作是二进制数)。
如果没有可能的状态,则输出一行’IMPOSSIBLE’。


SAMPLE INPUT

10
1
-1
7 -1
在这个样例中,有10盏灯,只有1个按钮被按下。最后7号灯是关着的。


SAMPLE OUTPUT

0000000000
0101010101
0110110110


解题思路:

这道题可以通过数学推理来进行各种优化。首先需要理解的是结果是以6个灯为一组重复,所以我们只需要判断6个灯的情况。所以我用的是深度优先搜索的方式,通过计算可以判断出c>4时可以实现所有可能的按法(根据按钮之间的联系来推),而c<=4则通过深搜来进行枚举。当然根据按钮之间的关系可以让枚举次数变得更少,但代码会不简洁和明晰。由于可能会有不同的按法出现相同的结果,所以加了去重。

/*
ID: huanshi
LANG: C
TASK: lamps
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int N,C,lamp=63,v[7],flag=0,vl[64];//lamp记录六盏灯的情况,v数组记录题目要求,flag判断是否有结果,vl用来去重
FILE *fout;
void judge(){//判断是否符合要求int i,temp=0;for(i=1;i<=6;i++){//如果与题目不符则returnif(v[i]==0&&(lamp&(int)pow(2,6-i)))return ;if(v[i]==1&&!(lamp&(int)pow(2,6-i))) return ;temp+=lamp&(int)pow(2,6-i);//将灯的情况转换为统一的数字来去重(位运算可能会出现负数)}if(vl[temp])return ;//如果情况已出现过则returnvl[temp]=1;flag=1;return ;
}
void dfs(int step){//深搜if(step>C){judge();return ;}int i;lamp=~lamp;dfs(step+1);lamp=~lamp;//按钮1(注意要回溯)lamp=lamp^42;dfs(step+1);lamp=lamp^42;//按钮2lamp=lamp^21;dfs(step+1);lamp=lamp^21;//按钮3lamp=lamp^36;dfs(step+1);lamp=lamp^36;//按钮4
}
int main(){FILE *fin  = fopen ("lamps.in", "r");fout = fopen ("lamps.out", "w");fscanf(fin,"%d",&N);fscanf(fin,"%d",&C);if(C>4)C=4;int i,j,temp;for(i=0;i<7;i++)v[i]=99999;while(fscanf(fin,"%d",&temp)!=EOF&&temp!=-1){//记录亮的灯if(temp%6==0)temp=6;else temp%=6;v[temp]=1;}while(fscanf(fin,"%d",&temp)!=EOF&&temp!=-1){//记录关的灯if(temp%6==0)temp=6;else temp%=6;v[temp]=0;}dfs(1);for(j=0;j<64;j++){//顺序输出结果if(vl[j]){for(i=1;i<N;i++){if(i%6==0)fprintf(fout,"%d",j&(int)pow(2,0)&&1);//6的倍数特殊处理else fprintf(fout,"%d",j&(int)pow(2,6-i%6)&&1);}if(i%6==0)fprintf(fout,"%d",j&(int)pow(2,0)&&1);else fprintf(fout,"%d\n",j&(int)pow(2,6-i%6)&&1);}} if(flag==0)fprintf(fout,"IMPOSSIBLE\n");//没有答案则输出impossibleexit(0);
}

这篇关于USACO-Section2.2 Party Lamps【深度优先搜索】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/896377

相关文章

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

五大特性引领创新! 深度操作系统 deepin 25 Preview预览版发布

《五大特性引领创新!深度操作系统deepin25Preview预览版发布》今日,深度操作系统正式推出deepin25Preview版本,该版本集成了五大核心特性:磐石系统、全新DDE、Tr... 深度操作系统今日发布了 deepin 25 Preview,新版本囊括五大特性:磐石系统、全新 DDE、Tree

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

C# ComboBox下拉框实现搜索方式

《C#ComboBox下拉框实现搜索方式》文章介绍了如何在加载窗口时实现一个功能,并在ComboBox下拉框中添加键盘事件以实现搜索功能,由于数据不方便公开,作者表示理解并希望得到大家的指教... 目录C# ComboBox下拉框实现搜索步骤一步骤二步骤三总结C# ComboBox下拉框实现搜索步骤一这

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h