博弈-sg函数的原理和优化(hdu-1536)

sg函数:sg函数是博弈中的确定一个position性质的一个函数,全称是sprague-grundy。

性质1:对于所有的p-position,都有sg = 0;对于所有的n-position都有sg != 0;

性质2:某点a的sg函数的值由它的后继的sg函数的值来决定,设后继为b, c, d, e……则sg(a) = mex(sg(a), sg(b), sg(c), sg(d), sg(e),……)

mex是不属于这个集合的最小非负整数。

应用范围:在此无环图中谁无法再次移动,便是输。(如果谁无法移动,便是赢,暂时不知如何解决。)

应用:通过判断该点,sg = 0是p点,sg != 0是N点。

构造sg函数的方法:

方法一:打表

例题:hdu-1536-S-nim 点击打开链接


[cpp] view plaincopyprint?
  1. /* 
  2. 收获: 
  3. */  
  4. #include<iostream>   
  5. #include<cstdlib>   
  6. #include<vector>   
  7. #include<map>   
  8. #include<cstring>   
  9. #include<set>   
  10. #include<string>   
  11. #include<algorithm>   
  12. #include<sstream>   
  13. #include<ctype.h>   
  14. #include<fstream>   
  15. #include<string.h>   
  16. #include<stdio.h>   
  17. #include<math.h>   
  18. #include<stack>   
  19. #include<queue>   
  20. #include<ctime>   
  21. //#include<conio.h>   
  22. using namespace std;  
  23.   
  24. const int INF_MAX=0x7FFFFFFF;  
  25. const int INF_MIN=-(1<<31);  
  26.   
  27. const double eps=1e-10;  
  28. const double pi=acos(-1.0);  
  29.   
  30. #define pb push_back   //a.pb( )   
  31. #define chmin(a,b) ((a)<(b)?(a):(b))   
  32. #define chmax(a,b) ((a)>(b)?(a):(b))   
  33.   
  34.   
  35. template<class T> inline T gcd(T a,T b)//NOTES:gcd(   
  36.   {if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}  
  37. template<class T> inline T lcm(T a,T b)//NOTES:lcm(   
  38.   {if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}  
  39.   
  40.   
  41. typedef pair<intint> PII;  
  42. typedef vector<PII> VPII;  
  43. typedef vector<int> VI;  
  44. typedef vector<VI> VVI;  
  45. typedef long long LL;  
  46. int dir_4[4][2]={{0,1},{-1,0},{0,-1},{1,0}};  
  47. int dir_8[8][2]={{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};  
  48. //下,左下,左,左上,上,右上,右,右下。   
  49.   
  50. //******* WATER ****************************************************************   
  51.   
  52.   
  53. const int MAXN = 10500;  
  54. bool judge[150];  
  55. int sg[MAXN];  
  56. int M[150];  
  57. const int Init = 1e7;  
  58. int Num;  
  59.   
  60. void input_m()  
  61. {  
  62.     for(int i = 0; i < Num; i++)  
  63.     {  
  64.         cin>>M[i];  
  65.     }  
  66.     return ;  
  67. }  
  68.   
  69. void debug()  
  70. {  
  71.     cout<<"sg function"<<endl;  
  72.     for(int i = 0; i < 100; i++)  
  73.     {  
  74.         cout<<i<<" "<<sg[i]<<endl;  
  75.     }  
  76.     return ;  
  77. }  
  78.   
  79. void getsg()  
  80. {  
  81.     for(int i = 0; i < MAXN; i++)  
  82.     {  
  83.         memset(judge, falsesizeof(judge));  
  84.         //int tsg = Init;   
  85.         for(int j = 0; j < Num; j++)  
  86.         {  
  87.             int ps = i - M[j];  
  88.             if(ps >= 0) judge[sg[ps]] = true;  
  89.         }  
  90.         //if(tsg == Init) tsg = 0;   
  91.         for(int j = 0; j < Num + 1; j++)  
  92.         {  
  93.             if(judge[j] == false)  
  94.             {  
  95.                 sg[i] = j;  
  96.                 break;  
  97.             }  
  98.         }  
  99.     }  
  100.     //debug();   
  101.     return ;  
  102. }  
  103. int main()  
  104. {  
  105.     //freopen("input.txt","r",stdin);   
  106.     //freopen("output.txt","w",stdout);   
  107.     while(cin>>Num, Num)  
  108.     {  
  109.         input_m();  
  110.         getsg();  
  111.         int num;  
  112.         cin>>num;  
  113.         while(num--)  
  114.         {  
  115.             int nn, tp;  
  116.             cin>>nn;  
  117.             int ret = 0;  
  118.             for(int i = 0; i < nn; i++)  
  119.             {  
  120.                 cin>>tp;  
  121.                 ret ^= sg[tp];  
  122.             }  
  123.             if(ret == 0) cout<<"L";  
  124.             else cout<<"W";  
  125.         }  
  126.         cout<<endl;  
  127.     }  
  128.     return 0;  
  129.     //printf("%.6f\n",(double)clock()/CLOCKS_PER_SEC);   
  130. }  
/*
收获:
*/
#include<iostream>
#include<cstdlib>
#include<vector>
#include<map>
#include<cstring>
#include<set>
#include<string>
#include<algorithm>
#include<sstream>
#include<ctype.h>
#include<fstream>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<stack>
#include<queue>
#include<ctime>
//#include<conio.h>
using namespace std;
const int INF_MAX=0x7FFFFFFF;
const int INF_MIN=-(1<<31);
const double eps=1e-10;
const double pi=acos(-1.0);
#define pb push_back   //a.pb( )
#define chmin(a,b) ((a)<(b)?(a):(b))
#define chmax(a,b) ((a)>(b)?(a):(b))
template<class T> inline T gcd(T a,T b)//NOTES:gcd(
{if(a<0)return gcd(-a,b);if(b<0)return gcd(a,-b);return (b==0)?a:gcd(b,a%b);}
template<class T> inline T lcm(T a,T b)//NOTES:lcm(
{if(a<0)return lcm(-a,b);if(b<0)return lcm(a,-b);return a*(b/gcd(a,b));}
typedef pair<int, int> PII;
typedef vector<PII> VPII;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef long long LL;
int dir_4[4][2]={{0,1},{-1,0},{0,-1},{1,0}};
int dir_8[8][2]={{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
//下,左下,左,左上,上,右上,右,右下。
//******* WATER ****************************************************************
const int MAXN = 10500;
bool judge[150];
int sg[MAXN];
int M[150];
const int Init = 1e7;
int Num;
void input_m()
{
for(int i = 0; i < Num; i++)
{
cin>>M[i];
}
return ;
}
void debug()
{
cout<<"sg function"<<endl;
for(int i = 0; i < 100; i++)
{
cout<<i<<" "<<sg[i]<<endl;
}
return ;
}
void getsg()
{
for(int i = 0; i < MAXN; i++)
{
memset(judge, false, sizeof(judge));
//int tsg = Init;
for(int j = 0; j < Num; j++)
{
int ps = i - M[j];
if(ps >= 0) judge[sg[ps]] = true;
}
//if(tsg == Init) tsg = 0;
for(int j = 0; j < Num + 1; j++)
{
if(judge[j] == false)
{
sg[i] = j;
break;
}
}
}
//debug();
return ;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
while(cin>>Num, Num)
{
input_m();
getsg();
int num;
cin>>num;
while(num--)
{
int nn, tp;
cin>>nn;
int ret = 0;
for(int i = 0; i < nn; i++)
{
cin>>tp;
ret ^= sg[tp];
}
if(ret == 0) cout<<"L";
else cout<<"W";
}
cout<<endl;
}
return 0;
//printf("%.6f\n",(double)clock()/CLOCKS_PER_SEC);
}

方法二:递归迭代

以下

[cpp] view plaincopyprint?
  1. #include"iostream"   
  2. #include"algorithm"   
  3. #include"string.h"   
  4. using namespace std;  
  5. int s[101],sg[10001],k;  
  6. int getsg(int m)  
  7. {  
  8.     int hash[101]={0};  
  9.     int i;  
  10.     for(i=0;i<k;i++){  
  11.         if(m-s[i]<0)  
  12.             break;  
  13.         if(sg[m-s[i]]==-1)  
  14.             sg[m-s[i]]=getsg(m-s[i]);  
  15.         hash[sg[m-s[i]]]=1;  
  16.     }  
  17.     for(i=0;;i++)  
  18.         if(hash[i]==0)  
  19.             return i;  
  20.    
  21.    
  22. }  
  23. int main()  
  24. {  
  25.     //int k;   
  26.    // freopen("game.in","r",stdin);   
  27.     //freopen("game.out","w",stdout);   
  28.     while(cin>>k,k)  
  29.     {  
  30.         int i;  
  31.         for(i=0;i<k;i++)  
  32.             cin>>s[i];  
  33.         sort(s,s+k);  
  34.         memset(sg,-1,sizeof(sg));  
  35.         sg[0]=0;  
  36.         int t;  
  37.         cin>>t;      
  38.         while(t--)  
  39.         {  
  40.                
  41.             int n,m;  
  42.             cin>>n;  
  43.             int ans=0;  
  44.             while(n--)  
  45.             {  
  46.                 cin>>m;  
  47.                 if(sg[m]==-1)  
  48.                     sg[m]=getsg(m);  
  49.                 ans^=sg[m];  
  50.             }  
  51.             if(ans)  
  52.                 cout<<'W';  
  53.             else cout<<'L';  
  54.         }  
  55.         cout<<endl;  
  56.     }  
  57.     return 0;  
  58. }  
#include"iostream"
#include"algorithm"
#include"string.h"
using namespace std;
int s[101],sg[10001],k;
int getsg(int m)
{
int hash[101]={0};
int i;
for(i=0;i<k;i++){
if(m-s[i]<0)
break;
if(sg[m-s[i]]==-1)
sg[m-s[i]]=getsg(m-s[i]);
hash[sg[m-s[i]]]=1;
}
for(i=0;;i++)
if(hash[i]==0)
return i;
}
int main()
{
//int k;
// freopen("game.in","r",stdin);
//freopen("game.out","w",stdout);
while(cin>>k,k)
{
int i;
for(i=0;i<k;i++)
cin>>s[i];
sort(s,s+k);
memset(sg,-1,sizeof(sg));
sg[0]=0;
int t;
cin>>t;    
while(t--)
{
int n,m;
cin>>n;
int ans=0;
while(n--)
{
cin>>m;
if(sg[m]==-1)
sg[m]=getsg(m);
ans^=sg[m];
}
if(ans)
cout<<'W';
else cout<<'L';
}
cout<<endl;
}
return 0;
}

是别人的代码:

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

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

相关文章

java项目中Classpath路径到底指的是哪里?

1、src不是classpath, WEB-INF/classes,lib才是classpath&#xff0c;WEB-INF/ 是资源目录, 客户端不能直接访问。 2、WEB-INF/classes目录存放src目录java文件编译之后的class文件&#xff0c;xml、properties等资源配置文件&#xff0c;这是一个定位资源的入口。 3、引用clas…

程序员的八个级别

2009年4月6日 陈皓 在面试时&#xff0c;你可能会被经常问到“在未来5年&#xff0c;你想干什么&#xff1f;”&#xff0c;这可能是一个比较难回答的问题。在中国&#xff0c;答案一般可能会是Team leader&#xff0c;Manager&#xff0c;或是Architect&#xff0c;Specialist…

一个具有Spring Boot,Spring Security和Stormpath的简单Web应用程序-15分钟

建筑物身份管理&#xff0c;包括身份验证和授权&#xff1f; 尝试Stormpath&#xff01; 我们的REST API和强大的Java SDK支持可以消除您的安全风险&#xff0c;并且可以在几分钟内实现。 注册 &#xff0c;再也不会建立auth了&#xff01; 更新 &#xff1a;我们最近发布了对…

Matlab各种分布的函数

正态分布&#xff1a;norm二项分布&#xff1a;bino卡方分布&#xff1a;chi2指数分布&#xff1a;exp柏松分布&#xff1a;poiss随机数&#xff1a;rnd密度函数&#xff1a;pdf累积概率&#xff1a;cdf逆累积分布&#xff1a;icdf&#xff0c;inv参数估计&#xff1a;fit对应组…

Python的配置文件模块yaml的使用

转自&#xff1a;君惜丶 简述 和GNU一样&#xff0c;YAML是一个递归着说“不”的名字。不同的是&#xff0c;GNU对UNIX说不&#xff0c;YAML说不的对象是XML。 YAML不是XML。 为什么不是XML呢&#xff1f;因为&#xff1a; YAML的可读性好。YAML和脚本语言的交互性好。YAML使用…

Matlab各种排序函数

sortsortrows 把整行的数据看作一个整体&#xff0c;对数据进行排序issorted, 判断是否已经排序了

位运算实例(一):判断奇偶性

同样一个问题&#xff0c;位运算可以提高程序的运行效率。 下面讲一下关于奇偶性的判断。 常规方法 public static boolean isOdd(int i){ return i % 2 ! 0; } 位运算方法 public static boolean isOdd(int i){ return (i & 1) ! 0; } 说明&#xff1a; 我们知道计算机中的…

Spring Security原理与应用

Spring Security是什么 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean&#xff08;注&#xff1a;包括认证与权限获取、配置、处理相关实例&#xff09;&#xff0c;充分利…

javafx2_JavaFX 2 GameTutorial第5部分

javafx2介绍 这是与JavaFX 2 Game Tutorial相关的六部分系列的第五部分。 我知道自从我写关于游戏的博客以来已经有很长时间了&#xff0c;但希望您仍然与我在一起。 如果您想回顾一下&#xff0c;请阅读第1部分 &#xff0c; 第2 部分 &#xff0c; 第3 部分和第4 部分 &#…

Matlab各种最值问题

最大最小maxmin求多个最小值,并返回其位置[B,ind] sort(A);B(1:n);前n个最小值ind(1:n);前n个最小值的位置

最长递增子序列问题的求解

最长递增子序列问题是一个很基本、较常见的小问题&#xff0c;但这个问题的求解方法却并不那么显而易见&#xff0c;需要较深入的思考和较好的算法素养才能得出良好的算法。由于这个问题能运用学过的基本的算法分析和设计的方法与思想&#xff0c;能够锻炼设计较复杂算法的思维…

史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)(Finchley版本)

转载请标明出处&#xff1a; 原文首发于&#xff1a;https://www.fangzhipeng.com/springcloud/2018/08/30/sc-f2-ribbon/ 本文出自方志朋的博客 在上一篇文章&#xff0c;讲了服务的注册和发现。在微服务架构中&#xff0c;业务都会被拆分成一个独立的服务&#xff0c;服务与服…

忽略已检查的异常,所有出色的开发人员都在这样做–基于600,000个Java项目

Github和Sourceforge上超过600,000个Java项目中的异常处理概述 Java是使用检查异常的少数语言之一。 它们在编译时强制执行&#xff0c;并且需要某种处理。 但是……实践中会发生什么&#xff1f; 大多数开发人员实际上处理任何事情吗&#xff1f; 以及他们如何做到的&#xf…

Matlab积分

yint(fx,x,a,b);%函数表达式&#xff0c;自变量&#xff0c;下限&#xff0c;上限注&#xff1a;求得到y为sym类型&#xff0c;不是数值&#xff0c;可以使用subs转换如&#xff1a;subs(y,1); subs(y,a,1);%第一个给y赋1&#xff0c;第二个给y中的a赋1

最长有序子序列—动态规划算法

动态规划使用范围&#xff1a;&#xff08;http://baike.baidu.com/view/28146.htm&#xff09; 任何思想方法都有一定的局限性&#xff0c;超出了特定条件&#xff0c;它就失去了作用。同样&#xff0c;动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效…

Codeforces 666E. Forensic Examination

Description 给出串 \(S\) ,和 \(m\) 个串 \(T_i\) ,每次询问 \((l,r,pl,pr)\) 表示 \(S[pl...pr]\) 在 \(T[l...r]\) 中哪一个出现次数最多,求出现次数和编号题面 Solution 基础题... 对于 \(S,T[l...r]\) 放在一起建广义后缀自动机 然后每次倍增到 S[pl,pr] ,然后查询子树内出…

Matlab控制精度

控制精度matlab控制运算精度用的是digits和vpa这两个函数digits用于规定运算精度&#xff0c;比如&#xff1a;digits(20);这个语句就规定了运算精度是20位有效数字。但并不是规定了就可以使用&#xff0c;因为实际编程中&#xff0c;我们可能有些运算需要控制精度&#xff0c;…

虚拟机环境下DPDK运行时的一些错误解决

在绑定网卡到DPDK模块时 报错 &#xff1a;is active. Not modifyingRouting table indicates that interface 0000:02:01.0 is active. Not modifying 解决方法&#xff1a; ifconfig <网卡名称> down 运行testpmd时无法分配内存&#xff1a;EAL: Error - exiting with …

ACM 网址和一些建议

USACO http://ace.delos.com/usacogate 美国著名在线题库&#xff0c;专门为信息学竞赛选手准备 TJU http://acm.tongji.edu.cn/ 同济大学在线题库&#xff0c;唯一的中文题库&#xff0c;适合NOIP选手 ZJU http://acm.zju.edu.cn/ 浙江大学在线题库 JLU http://acm.jlu…