欢迎大家订阅我的专栏:算法题解:C++与Python实现!
本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战!
专栏特色
1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的代码实现与详细指导,帮助您夯实算法基础。
2.系统化学习路径:按照算法类别和难度分级,从基础到进阶,循序渐进,帮助您全面提升编程能力与算法思维。
适合人群:
- 准备参加蓝桥杯、GESP、CSP-J、CSP-S等信息学竞赛的学生
- 希望系统学习C++/Python编程的初学者
- 想要提升算法与编程能力的编程爱好者
附上汇总贴:USACO历年白银组真题解析 | 汇总-CSDN博客
P6183 The Rock Game
【题目来源】
洛谷:P6183 [USACO10MAR] The Rock Game S - 洛谷
【题目描述】
在奶牛回家休息和娱乐之前,Farmer John 希望它们通过玩游戏获得一些智力上的刺激。
游戏板由n nn个相同的洞组成,这些洞最初都是空的。一头母牛要么用石头盖住一个空的洞,要么揭开一个先前被盖住的洞。游戏状态的定义是所有洞是否被石头覆盖的情况。
游戏的目标是让奶牛到达每个可能的游戏状态一次,最后回到初始状态。
以下是他们其中一次游戏的示例(空的洞用O表示,用石头盖住的洞用X表示):
| 时刻 | 洞 1 | 洞 2 | 洞 3 | 描述 |
|---|---|---|---|---|
| 0 00 | O | O | O | 一开始所有的洞都是空的 |
| 1 11 | O | O | X | 盖上洞 3 |
| 2 22 | X | O | X | 盖上洞 1 |
| 3 33 | X | O | O | 打开洞 3 |
| 4 44 | X | X | O | 盖上洞 2 |
| 5 55 | O | X | O | 打开洞 1 |
| 6 66 | O | X | X | 盖上洞 3 |
| 7 77 | X | X | X | 盖上洞 1 |
现在牛被卡住玩不下去了!他们必须打开一个洞,然而不管他们打开哪个洞,他们都会到达一个他们已经到达过的状态。例如,如果他们从第二个洞中取出岩石,他们将到达他们在时刻2 22已经访问过的状态(X O X)。
下面是一个 3 个孔的有效解决方案:
| 时间 | 洞 1 | 洞 2 | 洞 3 | 描述 |
|---|---|---|---|---|
| 0 00 | O | O | O | 一开始所有的洞都是空的 |
| 1 11 | O | X | O | 盖上洞 2 |
| 2 22 | O | X | X | 盖上洞 3 |
| 3 33 | O | O | X | 打开洞 2 |
| 4 44 | X | O | X | 盖上洞 1 |
| 5 55 | X | X | X | 盖上洞 2 |
| 6 66 | X | X | O | 打开洞 3 |
| 7 77 | X | O | O | 打开洞 2 |
| 8 88 | O | O | O | 打开洞 1,恢复到原来的状态 |
现在,奶牛们厌倦了这个游戏,它们想找你帮忙。
给定n nn,求游戏的有效解决方案序列。如果有多个解决方案,则输出任意一个。
【输入】
仅一行,一个整数n nn。
【输出】
共2 n + 1 2^n+12n+1行,每行一个长度为n nn的字符串,其中只包含字符O和X,该行中的第i ii个字符表示第i ii个孔在此状态下是被覆盖还是未覆盖,第一行和最后一行必须全部都是O。
【输入样例】
3【输出样例】
OOO OXO OXX OOX XOX XXX XXO XOO OOO【解题思路】
【算法标签】
《洛谷 P6183 The Rock Game》 #深度优先搜索,DFS# #USACO# #Special judge# #2010#
【代码详解】
#include<bits/stdc++.h>usingnamespacestd;intn,a[20],vis[65536];intans[65536][20];intcalc()// 将二进制数转为十进制数{intans=0;for(inti=1;i<=n;i++){ans=ans*2+a[i];}returnans;}voiddfs(intstep){if(step==pow(2,n)){// 当step等于2^n,就进行输出for(inti=1;i<=pow(2,n);i++){// 遍历ans二维数组for(intj=1;j<=n;j++){if(ans[i][j]==1)cout<<"X";// 如果当前位置为1就输出Xelsecout<<"O";// 否则就输出O}cout<<endl;// 每输出完后就换一行}exit(0);// 只要完成一组输出,就结束程序}for(inti=1;i<=n;i++){// 遍历1到n个位置a[i]=!a[i];// 对当前位置进行取反操作if(vis[calc()]==1){// 如果当前二进制数访问过a[i]=!a[i];// 还原现场continue;// 继续下一次循环}vis[calc()]=1;// 如果这个数之前没有出现过,则标记为1for(intj=1;j<=n;j++){// 使用二维数组记录下当前二进制数ans[step][j]=a[j];}dfs(step+1);// 进行下一次搜索vis[calc()]=0;// 还原现场a[i]=!a[i];}}intmain(){cin>>n;// 输入nfor(inti=1;i<=n;i++){// 先输出第一行全Ocout<<'O';}cout<<endl;vis[0]=1;// 标记全0的二进制数已经访问过dfs(1);// 进行dfs深搜return0;}【运行结果】
3 OOO XOO XXO OXO OXX XXX XOX OOX OOO