原题链接:蓝桥杯算法提高VIP-开灯游戏
解题思路:
模拟 + DFS。其中最巧妙的就是如何记录开关的某个组合出现过,当然是 Hash 值啦。
参考代码:
#include<bits/stdc++.h> /* 一共 112 个组合,5 ms 哟 */
using namespace std;
const int SIZE = 23277; /* 随便开个数啦 >v< */
bool Light[10];
bool Status[SIZE]; int Index; /* 存储开关的某个状态 */
/* 用结构体存储开关组合,用作排序输出 */
struct Ans {
char num[10];
} ans[144];
/* 模拟灯 */
void OPT(char button[], int num) {
/* 改变灯 */
if (num == 1) Light[2] = !Light[2], Light[4] = !Light[4];
else if (num == 2) Light[1] = !Light[1], Light[3] = !Light[3], Light[5] = !Light[5];
else if (num == 3) Light[2] = !Light[2], Light[6] = !Light[6];
else if (num == 4) Light[1] = !Light[1], Light[5] = !Light[5], Light[7] = !Light[7];
else if (num == 5) Light[2] = !Light[2], Light[4] = !Light[4], Light[6] = !Light[6],
Light[8] = !Light[8];
else if (num == 6) Light[3] = !Light[3], Light[5] = !Light[5], Light[9] = !Light[9];
else if (num == 7) Light[4] = !Light[4], Light[8] = !Light[8];
else if (num == 8) Light[5] = !Light[5], Light[7] = !Light[7], Light[9] = !Light[9];
else if (num == 9) Light[6] = !Light[6], Light[8] = !Light[8];
/* 改变开关 */
if (button[num - 1] == '1')
button[num - 1] = '0';
else
button[num - 1] = '1';
}
/* Hash函数计算开关某个状态对应的一个值 */
int Hash(char button[]) {
int hash = 0;
for (int i = 1; i < 10; i++)
hash = hash * i + button[i - 1] + 7;
return hash % 16529; /* 16529 是一个素数 */
}
/* 判断当前灯是否亮了 4 盏 */
bool Judge() {
int total = 0;
for (int i = 1; i < 10; i++)
if (Light[i])
total++;
return total == 4;
}
void DFS(char now[]) {
if (Judge()) {
strcpy(ans[Index++].num, now); return;
}
/* 每个按钮都一遍 */
for (int button = 1; button < 10; button++) {
OPT(now, button); /* 按下去.jpg */
int StatusValue = Hash(now); /* 计算开关状态值 */
if (!Status[StatusValue]) {
Status[StatusValue] = true;
DFS(now); /* 继续到处按 */
}
OPT(now, button); /* 回溯 */
}
}
bool cmp(Ans ans1, Ans ans2) {
return strcmp(ans1.num, ans2.num) < 0;
}
int main() {
/*clock_t Sta = clock();*/
char init[] = "000000000"; /* 初始状态全关闭 */
Status[Hash(init)] = true; DFS(init);
sort(ans, ans + Index, cmp);
for (int i = 0; i < Index; i++)
printf("%s\n", ans[i].num);
/*clock_t End = clock();
cout << (double)(End - Sta) / CLOCKS_PER_SEC << endl;*/
}0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复