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

相关文章

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

usaco 1.3 Calf Flac(暴搜)

思路是暴搜。 需要注意的地方是输入的方法,以及输出时的换行。 代码: /*ID: who jayLANG: C++TASK: calfflac*/#include<stdio.h>#include<string.h>#include<math.h>int main(){freopen("calfflac.in","r",stdin);freopen("calfflac.ou

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

usaco 1.2 Palindromic Squares(进制转化)

考察进制转化 注意一些细节就可以了 直接上代码: /*ID: who jayLANG: C++TASK: palsquare*/#include<stdio.h>int x[20],xlen,y[20],ylen,B;void change(int n){int m;m=n;xlen=0;while(m){x[++xlen]=m%B;m/=B;}m=n*n;ylen=0;whi