算法学习笔记(博弈论中的SG函数)

定义 S G SG SG函数:

对于状态 x x x和它的所有 k k k个后继状态 y 1 , y 2 , . . . , y k y_1, y_2,...,y_k y1,y2,...,yk

S G ( x ) = m e x { S G ( y 1 ) , S G ( y 2 ) , . . . , S G ( y k ) } SG(x) = mex\{SG(y_1), SG(y_2), ..., SG(y_k)\} SG(x)=mex{SG(y1),SG(y2),...,SG(yk)}

( m e x mex mex函数的值表示不属于集合的最小非负整数)

现在对所有起点的 S G SG SG函数值做异或和,若异或和为 0 0 0,则这个状态为必败状态。若不为 0 0 0,则为必败状态。

现给出证明:

当一个状态没有后继状态时,求 m e x mex mex集合为空集合, S G SG SG函数的值为 0 0 0。即最终态的 S G SG SG函数值必为 0 0 0,而对于一个 S G SG SG函数值不为 0 0 0的状态,在由他的后继状态组成的节点中,肯定会存在一个节点的 S G SG SG函数值为 0 0 0,也就是说,对于一个 S G SG SG函数值不为 0 0 0的状态,总是存在一个操作使它走向一个 S G SG SG函数值为 0 0 0的状态。

而对于一个 S G SG SG函数值为 0 0 0的状态,在由他的后继状态组成的节点中,肯定不存在一个节点的 S G SG SG函数值为 0 0 0

所以类比 N i m Nim Nim游戏(算法学习笔记(Nim游戏)),我们可以得出上述 S G SG SG定理。

S G SG SG定理适用于任何公平的两人游戏,它常被用于决定游戏的输赢结果。

在使用方面,常常通过记忆化搜索打表,再从表中寻找结果的规律,最后化简 S G SG SG函数的求值方法。

例题:[SDOI2009] E&D

[SDOI2009] E&D

题目描述

小 E 与小 W 进行一项名为 E&D 游戏。

游戏的规则如下:桌子上有 2 n 2n 2n 堆石子,编号为 1 ∼ 2 n 1 \sim 2n 12n。其中,为了方便起见,我们将第 2 k − 1 2k-1 2k1 堆与第 2 k 2k 2k 堆( 1 ≤ k ≤ n 1 \le k \le n 1kn)视为同一组。第 i i i 堆的石子个数用一个正整数 S i S_i Si 表示。

一次分割操作指的是,从桌子上任取一堆石子,将其移走。然后分割它同一组的另一堆石子,从中取出若干个石子放在被移走的位置,组成新的一堆。操作完成后,所有堆的石子数必须保证大于 0 0 0。显然,被分割的一堆的石子数至少要为 2 2 2。两个人轮流进行分割操作。如果轮到某人进行操作时,所有堆的石子数均为 1 1 1,则此时没有石子可以操作,判此人输掉比赛。

小 E 进行第一次分割。他想知道,是否存在某种策略使得他一定能战胜小 W。因此,他求助于小 F,也就是你,请你告诉他是否存在必胜策略。例如,假设初始时桌子上有 4 4 4 堆石子,数量分别为 1 , 2 , 3 , 1 1,2,3,1 1,2,3,1。小 E 可以选择移走第 1 1 1 堆,然后将第 2 2 2 堆分割(只能分出 1 1 1 个石子)。接下来,小 W 只能选择移走第 4 4 4 堆,然后将第 3 3 3 堆分割为 1 1 1 2 2 2。最后轮到小 E,他只能移走后两堆中数量为 1 1 1 的一堆,将另一堆分割为 1 1 1 1 1 1。这样,轮到小 W 时,所有堆的数量均为 1 1 1,则他输掉了比赛。故小 E 存在必胜策略。

输入格式

本题有多组数据。

第一行一个整数 T T T,表示数据组数。

对于每组数据:

第一行一个整数 N N N,表示桌子上共有 N N N 堆石子,这里的 N N N 即为题目描述中的 2 n 2n 2n

第二行 N N N 个整数 S 1 … N S_{1 \dots N} S1N

输出格式

对于每组数据,如果小 E 必胜,则一行一个字符串 YES,否则一行一个字符串 NO

样例 #1

样例输入 #1

2
4
1 2 3 1
6
1 1 1 1 1 1

样例输出 #1

YES
NO

提示

对于 20 % 20\% 20% 的数据, N = 2 N=2 N=2

对于另外 20 % 20\% 20% 的数据, N ≤ 4 N \le 4 N4 S i ≤ 50 S_i \le 50 Si50

对于 100 % 100\% 100% 的数据, 1 ≤ T ≤ 20 1 \le T \le 20 1T20 1 ≤ N ≤ 2 × 1 0 4 1 \le N \le 2 \times 10^4 1N2×104 N N N 为偶数, 1 ≤ S i ≤ 2 × 1 0 9 1 \le S_i \le 2 \times 10^9 1Si2×109


接下来直接给出未降低复杂度的暴力代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e4 + 9;int a[N];map<pair<int, int>, int> mp;       //做记忆化搜索int mex(set<int> &st)               //求mex值
{for(int i = 0; ; ++i)if(st.find(i) == st.end())return i;
}int sg(int x, int y)                
{//不妨设x >= yif(x < y) return sg(y, x);if(y == 0) return 0;if(mp.count({x, y})) return mp[{x, y}];set<int> st; //枚举所有后继状态,递归求得该状态SG函数的值for(int i = 1; i < x; ++i) st.insert(sg(x - i, i));for(int i = 1; i < y; ++i) st.insert(sg(i, y - i));return mp[{x, y}] = mex(st);
}void solve()
{int n; cin >> n;for(int i = 1; i <= n; ++i) cin >> a[i];int ans = 0;for(int i = 1; i <= n; i += 2){ans ^= sg(a[i], a[i + 1]);}cout << (ans ? "YES" : "NO") << '\n';
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _; cin >> _;while(_--) solve();return 0;
}

后面给出打表代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e4 + 9;int a[N];map<pair<int, int>, int> mp;int mex(set<int> &st)
{for(int i = 0; ; ++i)if(st.find(i) == st.end())return i;
}int sg(int x, int y)
{if(x < y) return sg(y, x);if(y == 0) return 0;if(mp.count({x, y})) return mp[{x, y}];set<int> st; for(int i = 1; i < x; ++i) st.insert(sg(x - i, i));for(int i = 1; i < y; ++i) st.insert(sg(i, y - i));return mp[{x, y}] = mex(st);
}void table(int n)   //打表
{cout << "    ";for(int i = 1; i <= n; ++i) cout << setw(2) << i << ' ';cout << '\n';for(int i = 1; i <= n; ++i){cout << setw(2) << i << ' ';for(int j = 1; j <= n; ++j){cout << setw(2) << sg(i, j) << ' ';}cout << '\n';}
}void solve()
{int n; cin >> n;for(int i = 1; i <= n; ++i) cin >> a[i];int ans = 0;for(int i = 1; i <= n; i += 2){ans ^= sg(a[i], a[i + 1]);}cout << (ans ? "YES" : "NO") << '\n';
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int n; cin >> n;table(n);// int _; cin >> _;// while(_--) solve();return 0;
}

从表中不难发现,(感兴趣可以复制上述代码把表打出来看一看),对于 x x x y y y都是奇数的状态,他们的 S G SG SG值都为 0 0 0

而对于一个及以上参数为偶数时,状态 { x , y } \{x,y\} {x,y} S G SG SG函数值就等于状态 { ( x + 1 ) / 2 , ( y + 1 ) / 2 } \{(x + 1) / 2, (y + 1) / 2\} {(x+1)/2,(y+1)/2} S G SG SG函数值加上一。

所以最终代码就可以缩短为:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e4 + 9;int a[N];int sg(int x, int y)
{if(x < y) return sg(y, x);if((x & 1) && (y & 1)) return 0;if(y % 2 == 0) return sg((x + 1) / 2, y / 2) + 1;if(x % 2 == 0) return sg(x / 2, (y + 1) / 2) + 1;
}void solve()
{int n; cin >> n;for(int i = 1; i <= n; ++i) cin >> a[i];int ans = 0;for(int i = 1; i <= n; i += 2){ans ^= sg(a[i], a[i + 1]);}cout << (ans ? "YES" : "NO") << '\n';
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int _; cin >> _;while(_--) solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/10473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android中gradle.properties 和 gradle-wrapper.properties 作用

我们更深入地了解这两个文件的作用和它们可以包含的一些常见配置。 gradle.properties gradle.properties文件是一个标准的Java属性文件&#xff0c;它允许你为Gradle构建配置全局属性。这些属性可以在项目的任何地方使用&#xff0c;包括项目的子项目。以下是一些常见的配置…

2024数维杯B题详细思路代码数学建模高质量保姆级

2024年第九届数维杯大学生数学建模挑战赛题目 B 题 生物质和煤共热解问题的研究 &#xff08;1&#xff09;基于附件一&#xff0c;请分析正己烷不溶物(INS)对热解产率&#xff08;主要 考虑焦油产率、水产率、焦渣产率&#xff09;是否产生显著影响&#xff1f;并利用图像 加…

工业机器人应用实践之玻璃涂胶(篇二)

工业机器人 接上篇文章&#xff0c;浅谈一下实践应用&#xff0c;具体以玻璃涂胶为例&#xff1a; 了解工业机器人在玻璃涂胶领域的应用认识工具坐标系的标定方法掌握计时指令的应用掌握人机交互指令的应用掌握等待类指令用法&#xff08;WaitDI、WaitUnitl 等&#xff09;认…

02 Linux编程-文件

1、文件描述符 对于内核而言&#xff0c;所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或者创建一个新文件时&#xff0c;内核向进程返回一个文件描述符。当读写一个文件时&#xff0c;用open和creat返回的文件描述符标识该文件&#xff0c;将…

n5.树(中)

1、二叉树的遍历 1.1先序、中序、后序遍历 先序遍历 根->左->右 先序遍历先访问根节点&#xff0c;再访问它的左子树&#xff0c;然后访问它的右子树。对于每次访问到的结点&#xff0c;都要递归地访问左子树、后右子树———递归。 创建 typedef struct TreeNode*…

点云体积计算方法之一 附python代码

一句话描述思路:通过统计计算点云所占用的体素的数量来计算点云的近似体积。这是一个粗略的近似值,对于复杂的形状可能不准确。 另外需要注意,这个只适合点云密集分布的场景来计算体积,比如树木扫描的体积;如果只是有表面积扫描的点云,该方法就不能计算整个物体的体积了…

飞跨电容型的三电平(FC-NPC)逆变器simulink仿真模型

本人搭建了飞跨电容型的三电平逆变器simulink仿真模型&#xff0c;相较于二极管钳位型三电平逆变器而言&#xff0c;钳位二极管变为飞跨的电容。采用SPWM调制和均流均压控制&#xff0c;通过搭建仿真模型得到三电平波形。 三电平拓扑中的飞跨电容是指在电路的输出端使用电容来实…

书生作业:LMDeploy

自己随便说几句。 关于模型部署&#xff0c;很有趣的一件事就是&#xff0c;它一路随着深度学习训练一起发展&#xff0c;尽管例如tensorrt等工具的出现&#xff0c;不断试图降低部署门槛&#xff0c;但是实际上&#xff0c;每一次AI的升级&#xff0c;似乎让这个细分领域没有…

C++面向对象

面向对象的三大特征 封装 目的:隐藏实现细节,实现模块化。特性: 访问权限 public:对所有对象开放。protected:对子类开放。private:只对自己开放。可以通过友元类打破 private 限定。对属性和方法进行限定。class A {friend class B; // B 可以访问 c public:int a;void …

图片格式不对怎么转换?推荐几个图片转换的高效处理方法

在日常使用电脑或处理图片的过程中&#xff0c;我们经常会遇到图片格式不兼容的问题&#xff0c;例如&#xff0c;我们可能收到了一个无法打开的图片文件&#xff0c;或者想将图片转换为其他格式以便在不同的应用程序中使用&#xff0c;这时候就需要将图片转格式&#xff0c;所…

如何让组织充满活力?你需要做好这七步

组织活力&#xff0c;通俗点说就是&#xff1a; 从竞争对手角度看&#xff0c;组织活力强的组织能做到竞争对手做不到的事情&#xff1b; 从客户角度看&#xff0c;组织活力强的组织&#xff0c;客户感受好&#xff1b; 从员工角度看&#xff0c;组织活力强的组织&#xff0c…

salesforce inactive user 和 deactived user 的区别

在Salesforce中&#xff0c;“inactive user”和“deactivated user”都指的是不再活跃或被停用的用户&#xff0c;但它们在某些情况下可能有不同的含义。 Inactive User&#xff08;非活跃用户&#xff09;&#xff1a;一个用户被标记为“非活跃”时&#xff0c;通常是因为他们…

算法题① —— 数组专栏

1. 滑动窗口 1.1 长度最小的子数组 力扣&#xff1a;https://leetcode.cn/problems/minimum-size-subarray-sum/description/ int minSubArrayLen(int s, vector<int>& nums) {int result INT32_MAX; int sum 0; // 子序列的数值之和int subLength 0; // 子序列…

基于单片机的直流电机检测与控制系统

摘要&#xff1a; 文章设计一款流电机控制系统&#xff0c;以 STC89C51 作为直流电机控制系统的主控制器&#xff0c;采用 LM293 做为驱动器实现 对直流电机的驱动&#xff0c;采用霍尔实现对直流电机速度的检测&#xff1b;本文对直流电机控制系统功能分析&#xff0c;选择确…

WAAP全站防护理念,发现和保护敏感数据

数据是现代企业的新石油&#xff1a;正确使用它可以促进公司的发展并帮助企业在竞争中领先。就像石油一样&#xff0c;原始数据和未被发现的数据是毫无用处的&#xff0c;企业将无法从中受益&#xff1b;在最坏的情况下&#xff0c;它可能会导致安全事件。这也是企业投资敏感数…

巩固学习4

python中函数逆置的几种方法 s input()for i in range(len(s)-1,-1,-1):#从最后一位开始&#xff0c;步长为-1print(s[i],end)用for语句循环逆置 s input() s list(s) n len(s) for i in range(n//2):s[i],s[n-1-i] s[n-1-i],s[i]#从中间反转字符串 res "".j…

A计算机上的程序与B计算机上部署的vmware上的虚拟机的程序通讯 如何配置?

环境&#xff1a; 在A计算机上运行着Debian11.3 Linux操作系统&#xff1b;在B计算机上运行着Windows10操作系统&#xff0c;并且安装了VMware软件&#xff0c;然后在VMware上创建了虚拟机C并安装了CentOS 6操作系统 需求&#xff1a; 现在A计算机上的程序需要同虚拟机C上的软…

(十二)JSP教程——exception对象

exception对象用来发现、捕获和处理JSP页面中的异常&#xff0c;是JSP文件运行时产生的异常对象。如果要使用它&#xff0c;必须将对应的JSP的page指令的isErrorPage属性设置为ture&#xff0c;即&#xff1a;<% page isErrorPage”true”%>。 JSP文件在运行中有异常现象…

【负载均衡式在线OJ项目day6】源文件路由功能及文件版题库构建

一.前言 前文讲到了OJ模块的设计思路&#xff0c;毫无疑问这是一个网络服务&#xff0c;我们先使用httplib&#xff0c;将源文件的路由功能实现&#xff0c;先把框架写好&#xff0c;后续再更改回调方法。 随后计划编写Modify模块&#xff0c;提供增删查改题库的功能(主要是查…

【贪心算法】最小生成树Kruskal算法Python实现

文章目录 [toc]问题描述最小生成树的性质证明 Kruskal算法Python实现时间复杂性 问题描述 设 G ( V , E ) G (V , E) G(V,E)是无向连通带权图&#xff0c; E E E中每条边 ( v , w ) (v , w) (v,w)的权为 c [ v ] [ w ] c[v][w] c[v][w]如果 G G G的一个子图 G ′ G^{} G′是…