http://acm.nyist.net/JudgeOnline/problem.php?pid=401&&简单的博弈论

本文解析了一种两人轮流从环状排列的硬币中移除硬币的游戏策略。通过分析不同情况下获胜者的确定方法,提供了两种游戏场景的AC代码实现。一种是针对环状硬币的取法,另一种是传统取石子游戏。
After hh has learned how to play Nim game, he begins to try another coin game which seems much easier.



The game goes like this:
Two players start the game with a circle of n coins.
They take coins from the circle in turn and every time they could take 1~K continuous coins.
(imagining that ten coins numbered from 1 to 10 and K equal to 3, since 1 and 10 are continuous, you could take away the continuous 10 , 1 , 2 , but if 2 was taken away, you couldn't take 1, 3, 4, because 1 and 3 aren't continuous)
The player who takes the last coin wins the game.
Suppose that those two players always take the best moves and never make mistakes.
Your job is to find out who will definitely win the game.
输入
The first line is a number T(1<=T<=100), represents the number of case. The next T blocks follow each indicates a case.
Each case contains two integers N(3<=N<=109,1<=K<=10).
输出
For each case, output the number of case and the winner "first" or "second".(as shown in the sample output)
样例输入
2
3 1
3 2样例输出
Case 1: first

Case 2: second

这是一道我们学校对外赛的月赛题,比赛时本来我是要做对外的题,听zmh童鞋说,选的大部分都是oj的老题,,于是就没有做对外赛了,直接做了队内的题,结果这道题愣是木做,然后在比赛后我看了这道题,却不知怎么做,不是木思路而是我看见关于数学方面的题我就不想弄,大概是我数学学得不好的原因吧。下面说一下这道题的思路,,,我认为这和我们oj的取石子一挺像的,在这里是把石子连接成环。首先第一直觉感觉后取赢得可能性大些,但凭直觉是不行的,下面简单说一下吧,对于先取的而言,只要取一次,石子环就变成石子链,而后取者只要每次在先取者对称的地方取相同的就行,这里只要先取者有的取,后取者也一定有的取。所以说大部分后取的赢。什么时候先取的赢呢,有两种情况,一是总的石子小于一次取的,其次是最多取连续的一个,并且石子的个数为奇数。

AC代码:

#include<iostream> #include<string.h> using namespace std; int main() { int Case; cin>>Case; for(int i=1;i<=Case;++i) { int n,m; cin>>n>>m; if(m>=n||(m==1&&n%2==1)) cout<<"Case "<<i<<": first" <<endl; else cout<<"Case "<<i<<": second" <<endl; }return 0; }
下面也顺便说一下取石子一把,就是如果可以一次性取完则先取者赢,下面一种情况就是,看总石子数对(k+1)取余是不是为零,如果为零,则后取者赢,否者先取者赢。

这里k为一次最多取的个数。

AC代码:

#include<stdio.h> main() { int n,m,p; scanf("%d",&n); while(n--) { scanf("%d%d",&m,&p); if(p>=m) printf("Win\n"); else { if(m%(p+1)==0) printf("Lose\n"); else printf("Win\n"); } } }

<think>嗯,用户需要一份能够模拟浏览器操作(BACK、FORWARD、VISIT、QUIT)的C++代码。我之前已经给出过一个实现,现在用户又引用了其他资料,可能需要更简洁或更符合特定要求的代码。首先,我需要回顾用户提供的引用内容,看看是否有新的信息需要整合。 引用1中的代码用了两个栈,backward和forward,初始页面是csw.jlu.edu.cn。处理VISIT时,将当前页面压入backward栈,并清空forward栈。BACK操作时,如果backward不为空,弹出顶部作为当前页面,并将原来的当前页面压入forward栈。FORWARD类似,但操作的是forward栈。输出直接对应每个命令的结果,例如VISIT后输出网址,BACK或FORWARD成功则输出网址,否则Ignored。 引用2提到了使用栈和队列来保存历史记录和输出记录,但用户的问题可能不需要队列,只需要栈。引用3和4都提到了使用两个栈的结构,backStack和forwardStack,这与之前的思路一致。 用户当前的问题是需要一个简单的C++代码,支持这四个命令。需要确保初始页面是http://www.acm.org/,符合样例输入输出。需要处理每个命令的正确输出,比如BACK失败输出Ignored,VISIT输出访问的网址,QUIT退出。 现在需要整合这些信息,写出一个结构清晰、符合题意的代码。代码的关键点包括: 1. 使用两个栈:back和forward。 2. 当前页面current初始化为http://www.acm.org/。 3. VISIT操作时,将current压入back栈,清空forward栈,更新current为新网址,并输出该网址。 4. BACK操作时,如果back栈不为空,弹出顶部到current,并将原current压入forward栈,输出current;否则输出Ignored。 5. FORWARD操作时,如果forward栈不为空,弹出顶部到current,并将原current压入back栈,输出current;否则输出Ignored。 6. QUIT退出循环。 需要注意样例输入中的处理,比如在连续BACK之后无法继续则输出Ignored。例如,初始页面是A,VISIT B,VISIT C,此时back栈中有A和B,current是C。第一次BACK到B,back栈剩下A,current是B,forward栈压入C。再次BACK到A,此时back栈为空,再次BACK则输出Ignored。之后FORWARD会回到B,再C? 另外,当执行VISIT后,forward栈需要清空,因为新的访问会破坏前进历史。 代码结构方面,可以使用循环读取命令,根据不同的命令执行对应的操作。注意处理输入,每个命令可能是VISIT后跟网址,或者其他命令不带参数。 例如,样例输入中的第一个命令是VISIT http://acm.ashland.edu/,此时current是初始页面http://www.acm.org/,将其压入back栈,forward栈清空,current更新为新网址,并输出该网址。 在样例中,当执行多次BACK后,比如第三次BACK时,back栈已经为空,所以输出Ignored。此时current仍然是初始页面,不会改变。 需要确保每次操作后的状态正确,并且输出符合要求。例如,在VISIT之后输出网址,BACK和FORWARD成功时输出网址,否则Ignored。 现在考虑代码实现。需要包含必要的头文件,如iostream, stack, string。使用命名空间std。主函数中定义两个栈back和forward,以及current字符串初始化为http://www.acm.org/。然后循环读取命令,直到遇到QUIT。 处理VISIT时,读取url,将current压入back栈,清空forward栈,current更新为url,并输出url。 处理BACK时,如果back不为空,弹出顶部到current,原current压入forward栈,输出current。否则输出Ignored。 处理FORWARD时,如果forward不为空,弹出顶部到current,原current压入back栈,输出current。否则输出Ignored。 QUIT时退出循环。 需要注意,初始页面在第一次VISIT之前已经被设置为http://www.acm.org/,所以在第一次VISIT时,current不为空,会被压入back栈。 测试样例输入,确保输出正确。例如,样例输入中的第一个VISIT后输出对应的网址,BACK三次后第三次输出Ignored,FORWARD成功则输出对应的网址,否则Ignored。 现在编写代码,确保符合这些逻辑。</think>根据需求实现浏览器导航功能,以下是符合题目要求的C++代码实现: ```cpp #include <iostream> #include <stack> #include <string> using namespace std; int main() { stack<string> back, forward; string current = "http://www.acm.org/"; string cmd, url; while (cin >> cmd && cmd != "QUIT") { if (cmd == "VISIT") { cin >> url; back.push(current); current = url; while (!forward.empty()) forward.pop(); cout << current << endl; } else if (cmd == "BACK") { if (back.empty()) { cout << "Ignored" << endl; } else { forward.push(current); current = back.top(); back.pop(); cout << current << endl; } } else if (cmd == "FORWARD") { if (forward.empty()) { cout << "Ignored" << endl; } else { back.push(current); current = forward.top(); forward.pop(); cout << current << endl; } } } return 0; } ``` #### 核心实现要点 1. **数据结构**:使用两个栈`back`和`forward`分别存储后退/前进历史 2. **初始状态**:当前页面初始化为`http://www.acm.org/` 3. **VISIT操作**: - 将当前页面压入`back`栈 - 清空`forward`栈(新访问会破坏前进历史) - 更新当前页面并输出[^3] 4. **BACK操作**: - 若`back`栈非空,弹出顶部元素作为新页面 - 原页面压入`forward`栈 - 输出新页面或"Ignored"[^4] 5. **FORWARD操作**: - 若`forward`栈非空,弹出顶部元素作为新页面 - 原页面压入`back`栈 - 输出新页面或"Ignored"[^5] #### 测试样例验证 输入样例执行流程: ``` 操作顺序 | back栈变化 | forward栈变化 | 当前页面 --------------------------------------------------------------------------------------- 初始状态 | [] | [] | http://www.acm.org/ VISIT A | [初始] | [] | A VISIT B | [初始, A] | [] | B BACK → A | [初始] | [B] | A BACK → 初始 | [] | [B, A] | 初始 BACK → Ignored | [] | [B, A] | 初始 FORWARD → A | [初始] | [B] | A VISIT IBM | [初始, A] | [] | IBM BACK → A | [初始] | [IBM] | A BACK → 初始 | [] | [IBM, A] | 初始 VISIT C# | [初始] | [] | C# BACK → 初始 | [] | [C#] | 初始 FORWARD → C# | [初始] | [] | C# FORWARD → Ignored | [初始] | [] | C# ``` #### 相关扩展问题 1. 如何处理浏览器历史记录持久化存储? 2. 如何实现带时间戳的访问历史追踪? 3. 当历史记录超过内存限制时,如何设计LRU淘汰策略? [^1]: 基础栈结构实现导航功能 [^3]: 新访问会清空前进历史 [^4]: 后退时更新前进栈 [^5]: 前进时更新后退栈
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值