【292】 Nim Game (2019年3月12日,E)

有一堆石头,游戏规则是每次可以从里面拿1-3颗石头,拿到最后的石头的人赢。你和你的对手都 optimal 的玩这个游戏,问先手(也就是你)能不能赢得这个比赛。

题解:我本来写的是 dfs + memo,但是没想到这个题数字太大了。容易爆栈。后来通过看discuss和观察,发现,这个题,只要不是 4 的倍数,先手都能赢得比赛。

 class Solution {
public:
bool canWinNim(int n) {
return n % != ;
}
};

【375】Guess Number Higher or Lower II (2019年3月12日,google tag,H)

给了 1 ~ N 这 N 个数字猜数,我来猜,如果我猜错了,我猜这个数为x,那么我就付 x 元。返回在能保证我赢的情况下,返回我必须付多少钱。

https://www.1point3acres.com/bbs/thread-197552-1-1.html

【464】Can I Win (2019年2月20日,谷歌tag,M)

给了一个1-100的游戏,游戏规则是,两个选手,player1每次从1-100中抽取一个数字,player2每次也从1-100中抽取一个数字,不能重复抽取相同的数字。直到某个player抽取到一个数,所有轮次中每个player抽取的数字加和大于等于target(target是提前给定的)。问player1能不能赢这个游戏。

本题的题目意思是把100换成一个变量叫做 maxChoosableInteger。问 player1 能不能赢这个游戏。

题解:这是一棵博弈树的问题。解空间如下图:

裸的dfs搜索方法如下:对于当前的局面,我们尝试用一个没有用过的数作为当前的解,然后dfs到下一个局面。

如果下个局面返回了false,就是对手不能赢,那我肯定非常高兴的马上返回了true,因为这个局面我能赢。(注意返回的时候要把当前局面用过的数字清空。回溯。不能忘。

但是如果下个局面返回了true,我就会认真反思自己,然后后悔当前局面的走法(是的,就是这么的无赖)去换一种新的走法。

那么对于当前局面的前一个局面来说,对手看到我返回了true,那他也可以反悔啊,他内心os:老子也不这么走了,我也要换一个走法。于是他就继续遍历他解空间的下一个解,直到他在当前空间找到了一个解,这个解能让他在当前空间赢,或者他找遍了所有的可能解,都赢不了,他只好认输,"我在当前空间赢不了,我返回false"。

 class Solution {
public:
bool canIWin(int maxChoosableInteger, int desiredTotal) {
if (desiredTotal <= ) {return true;}
if (maxChoosableInteger * (maxChoosableInteger + ) / < desiredTotal) {return false;}
string used(maxChoosableInteger, '');
int sum = ;
return canIWin(maxChoosableInteger, desiredTotal, sum, used);
}
bool canIWin(int maxChoosableInteger, int desiredTotal, int sum, string& used) {
if (sum >= desiredTotal) {return false;}
for (int i = ; i <= maxChoosableInteger; ++i) {
if (used[i-] == '') { continue; } //如果当前的数用过了,那么就换下一个能用的数
used[i-] = '';
if (canIWin(maxChoosableInteger, desiredTotal, sum + i, used) == false) {
//到这里需要回溯。如果下一个局面为false的话,就说明当前局面能赢。
//但是你想象一下如果你是一个玩家,当对手告诉你这个局面对手能赢的时候,你会怎么做,
//肯定是返回到一个有一个解-对手不能赢的层次,然后去dfs那个解空间。
used[i-] = '';
return true;
}
used[i-] = '';
}
return false;
}
};

再加上可以记忆化或者状态压缩的技巧。用个memo。

 class Solution {
public:
bool canIWin(int maxChoosableInteger, int desiredTotal) {
if (desiredTotal <= ) {return true;}
if (maxChoosableInteger * (maxChoosableInteger + ) / < desiredTotal) {return false;}
string used(maxChoosableInteger, '');
int sum = ;
return canIWin(maxChoosableInteger, desiredTotal, sum, used, );
}
unordered_map<string, bool> memo;
bool canIWin(int maxChoosableInteger, int desiredTotal, int sum, string& used, int player) {
if (sum >= desiredTotal) {return false;}
if (memo.find(used) != memo.end()) {return memo[used];}
string key = used;
memo[key] = false;
for (int i = ; i <= maxChoosableInteger; ++i) {
if (used[i-] == '') { continue; }
used[i-] = '';
if (canIWin(maxChoosableInteger, desiredTotal, sum + i, used, - player) == false) {
memo[key] = true;
used[i-] = '';
return true;
}
used[i-] = '';
}
return false;
}
};

【486】Predict the Winner

【843】Guess the Word (2019年3月12日,google tag)

给了一个 wordlist 猜单词,给了一个 api ,叫做 int guess(string word),返回我们的 target 单词有多少个位置和 word match。

For each test case, you have 10 guesses to guess the word. At the end of any number of calls, if you have made 10 or less calls to master.guess and at least one of these guesses was the secret, you pass the testcase.

题解:这道题不难,其实主要是这种交互式的问题在leetcode上第一次出现。

intuition: 我们先随机选一个单词 word,然后利用返回值 x,如果 target 和 word match 的有 x,那么我们只需要选择在 list 中和 word match x个位置的单词,这个作为我们下次选择的集合。

这么做能 ac。

但是可以优化:如果说我们随机选一个单词,但是如果 返回值 x == 0 的话,那么其实剩下的解可能很多。我们试图找一个单词,与这个单词有 0 个match 的单词解的集合最小就行了。

 /**
* // This is the Master's API interface.
* // You should not implement it, or speculate about its implementation
* class Master {
* public:
* int guess(string word);
* };
*/
class Solution {
public:
void findSecretWord(vector<string>& wordlist, Master& master) {
for (int t = ; t < ; ++t) {
int n = wordlist.size();
unordered_map<string, int> mp;
for (int i = ; i < n; ++i) {
for (int j = i + ; j < n; ++j) {
if (calMatch(wordlist[i], wordlist[j]) == ) {
mp[wordlist[i]]++;
}
}
}
pair<string, int> minmax = make_pair(wordlist[], );
for (auto& p : mp) {
if (p.second < minmax.second) {minmax = p;}
}
int x = master.guess(minmax.first);
if (x == ) {return;}
vector<string> list2;
for (auto& w : wordlist) {
if (calMatch(w, minmax.first) == x) {
list2.push_back(w);
}
}
wordlist = list2;
}
}
int calMatch(string& s, string& t) {
int match = ;
for (int i = ; i < s.size(); ++i) {
if (s[i] == t[i]) {match++;}
}
return match;
}
};

【913】Cat and Mouse

【LeetCode】一种博弈思路 minimax(共5题)的更多相关文章

  1. 【LeetCode】线段树 segment-tree(共9题)+ 树状数组 binary-indexed-tree(共5题)

    第一部分---线段树:https://leetcode.com/tag/segment-tree/ [218]The Skyline Problem [307]Range Sum Query - Mu ...

  2. 【LeetCode】链表 linked list(共34题)

    [2]Add Two Numbers (2018年11月30日,第一次review,ko) 两个链表,代表两个整数的逆序,返回一个链表,代表两个整数相加和的逆序. Example: Input: ( ...

  3. 【LeetCode】深搜DFS(共85题)

    [98]Validate Binary Search Tree [99]Recover Binary Search Tree [100]Same Tree [101]Symmetric Tree [1 ...

  4. 【LeetCode】回溯法 backtracking(共39题)

    [10]Regular Expression Matching [17]Letter Combinations of a Phone Number [22]Generate Parentheses ( ...

  5. 【LeetCode】前缀树 trie(共14题)

    [208]Implement Trie (Prefix Tree) (2018年11月27日) 实现基本的 trie 树,包括 insert, search, startWith 操作等 api. 题 ...

  6. 【LeetCode】随机化算法 random(共6题)

    [384]Shuffle an Array(2019年3月12日) Shuffle a set of numbers without duplicates. 实现一个类,里面有两个 api,struc ...

  7. 【LeetCode】拓扑排序 topological-sort(共5题)

    [207]Course Schedule [210]Course Schedule II [269]Alien Dictionary [329]Longest Increasing Path in a ...

  8. 【LeetCode】按 tag 分类索引 (900题以下)

    链表:https://www.cnblogs.com/zhangwanying/p/9797184.html (共34题) 数组:https://www.cnblogs.com/zhangwanyin ...

  9. Leetcode 简略题解 - 共567题

    Leetcode 简略题解 - 共567题     写在开头:我作为一个老实人,一向非常反感骗赞.收智商税两种行为.前几天看到不止两三位用户说自己辛苦写了干货,结果收藏数是点赞数的三倍有余,感觉自己的 ...

随机推荐

  1. Ubuntu 14.04 虚拟机配置固定ip地址

    Ubuntu 14.04 虚拟机配置固定ip地址: 虚拟机用的NAT方式配置: 1.虚拟机: 虚拟机→设置→网络适配器→NAT模式: 2.虚拟机:编辑→虚拟网络编辑器→更改设置→选择NAT→填入子网I ...

  2. 使用Windows service创建一个简单的定时器

    一.需求 我们有时候可能会想要做一些定时任务,例如每隔一段时间去访问某个网站,或者下载一些东西到我们服务器上等等之类的事情,这时候windows service 是一个不错的选择. 二.实现 1.打开 ...

  3. Linux内核设计与实现 总结笔记(第三章)进程

    进程管理 进程:处于执行期的程序. 线程:在进程中活动的对象 虚拟机制 虚拟处理器:多个进程分享一个处理器 虚拟内存:多个线程共享虚拟内存 一.进程描述符和任务结构 进程存放在双向循环链表中(队列), ...

  4. Solr核心(内核)

    Solr核心(内核)   Solr核心(Core)是Lucene索引的运行实例,包含使用它所需的所有Solr配置文件.我们需要创建一个Solr Core来执行索引和分析等操作. Solr应用程序可以包 ...

  5. 攻防世界 | when_did_you_born

    所以题目要求是输入生日1926 payload: from pwn import * io = remote("111.198.29.45",40803) io.recvline( ...

  6. cordova+vue做的app解决引入cordova-plugin-splashscreen后启动先显示黑屏在显示启动页

    先上项目目录结构cordova项目结构 android platform 结构 图中用红框框起来的为主要修改文件 这篇主要的讲cordova项目引用了cordova-plugin-splashscre ...

  7. Packet Tracer基本使用

    Cisco Packet Tracer基本使用 1:添加设备:路由器选择1841,交换机选择2960二层交换机,添加PC.服务器Server(End Devices) 2:添加连接:这里指以太网连接, ...

  8. jenkins持续集成、插件以及凭据

    Jenkins介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. Jenkins功能包括: ...

  9. 电脑可以识别sd卡手机无法识别 的解决方法。 我成功了。 淘宝买的sd卡 不用退货了。 退的人肝疼

    https://wenku.baidu.com/view/822e471055270722192ef736.html 电脑可以识别 sd 卡手机无法识别 * (本教程只是本人实际操作方法,可以解决一部 ...

  10. sysbench - 数据库功能及性能测试工具

    sysbench 的 GitHub 参考资料 1.0 之后的版本使用方法跟之前的有所区别,下面所有内容基于 1.0.9 版本. 另外,为了方便管理测试,最好不要通过命令直接运行测试,而是写成脚本自动化 ...