HDU1536,SG函数(①打表,②回溯),简单应用示例2
来源:互联网 发布:linux 文件夹访问权限 编辑:程序博客网 时间:2024/06/05 10:49
0
1
将游戏拆分成多个子游戏,求各自的sg值再异或。
如何求sg函数值?如果查询次数过多,可以预先打表,然后查;如果查询次数相对不多,但是题目卡时间,可以回溯法,求哪个查哪个。
打表还有一个好处,把所有可能用到的sg值都求了出来,如果对时间有进一步要求的题目,可以打表以后寻找sg函数值的规律,直接根据规律用数学式子求sg值,以达到O(1)的sg查询速度。
回溯的好处是在于不需要找规律,且在线查询sg值,查询时间略快于打表,因为它总是从要查找的sg值开始,然后往前回溯,如果遇到已知sg值就可以返回,并保存所有算过的sg值。比起打表,要查找的sg值可能远远小于最后一个数,这样就不用打表一直求到最后一个数。
2
①打表sg函数值(320ms):
#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>//#define Local_judge//HDU1536,SG函数,简单应用示例2using namespace std;int k,m,l;int number;int fib[110];int sg[10010];bool bj[10010];int res;void Get_sg(int t,int x){//x是sg数组上限,t是有多少种取石子的方法 memset(sg,0,sizeof(sg)); for(int i=1;i<=x;i++){ memset(bj,0,sizeof(bj)); for(int j=1;j<=t&&fib[j]<=i;j++){ bj[sg[i-fib[j]]]=1; } for(int j=0;j<=x;j++){ if(!bj[j]){ sg[i]=j; break; } } }}int main(){ #ifdef ONLINE_JUDGE//HDU上已经定义的宏 #else freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif // Judge /* #ifdef Local_judge //类似的,可以自己定义,提交时注释掉最上面的define Local_judge freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif // ACM */ while(~scanf("%d",&k)&&k){ for(int i=1;i<=k;i++){ scanf("%d",&fib[i]); } sort(fib+1,fib+1+k); scanf("%d",&m); Get_sg(k,10000);</p><p> //for(int i=0;i<=100;i++) cout<<sg[i]<<endl;</p><p> for(int i=1;i<=m;i++){ scanf("%d",&l); scanf("%d",&number); res=sg[number]; for(int j=2;j<=l;j++){ scanf("%d",&number); res^=sg[number]; } if(res==0){ cout<<"L"; } else{ cout<<"W"; } } cout<<endl; }}
②回溯在线求sg函数值(280ms):
#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>///注意一个缺陷:Sg_huisu中每次都要bool visted[n];memset();如果最大sg函数值n大一些,估计这个方法就爆栈了。所以理解这种回溯在线查找sg值的思想即可。using namespace std;int k,m,num,number;int s[110];int sg[10010];//sg上限是石子个数而不是石子堆堆数int Sg_huisu(int x){//很多人把这一步叫做dfs,但是我认为称为回溯更恰当一些。因为dfs找到合适的就return了, 而这里每一层都要返回一个结点出发到达的每一个节点的情况,然后进行比较,再返回上一层。 if(sg[x]!=-1) return sg[x]; bool visted[110];//visted[x],x上限是最大的sg函数值,你如果看不出来,可以打表所有sg值看看.... memset(visted,0,sizeof(visted)); for(int i=0;i<k;i++){ if(s[i]<=x){ Sg_huisu(x-s[i]); visted[sg[x-s[i]]]=1; } } for(int i=0;;i++){//同上一个注释,建立在visted数组内元素个数不超过最大sg值的基础上 if(!visted[i]){ sg[x]=i; break; } } return sg[x];}int main(){ while(~scanf("%d",&k)&&k){ for(int i=0;i<k;i++){ scanf("%d",&s[i]); } scanf("%d",&m); sort(s,s+k); memset(sg,-1,sizeof(sg));//针对分解后的子游戏,所以下文中几次询问或者每次询问时给出几个子游戏,对sg[]并没有影响。 while(m--){ scanf("%d",&num); int ans=0;//0^0=0,0^1=1; for(int j=0;j<num;j++){ scanf("%d",&number); ans^=Sg_huisu(number); } if(ans==0){ cout<<"L"; } else{ cout<<"W"; } } cout<<endl; }}
0 0
- HDU1536,SG函数(①打表,②回溯),简单应用示例2
- hdu1536 S-Nim (利用sg函数模板打表)
- HDU1536 SG函数的简单应用
- HDU1536 S-Nim(博弈入门暴力打SG表)
- S-Nim(hdu1536+SG函数)
- HDU1536->SG函数
- HDU1536 SG函数
- //HDU1848,SG函数,简单应用示例
- sg函数模板(打表)
- HDU5795 SG函数(打表然后归纳规律),示例3
- 【HDU1536】S-Nim (博弈,SG函数)
- hdu1536 & 1944 S-NIM 博弈 SG函数
- hdu1536 - S-Nim (博弈 SG函数)
- HDU1536&&HDU1944 S-Nim SG函数
- SG函数打表-HDU1848
- HDU 5795 A Simple Nim (sg函数 打表)
- HDU1536 或者POJ2960 S-Nim 传说中的SG函数
- hdu1536(求sg)
- float属性理解
- Java中equals和==的区别
- spring security下fileupload上传文件被拦截
- 高斯消元
- 前端新玩具——webGL简介
- HDU1536,SG函数(①打表,②回溯),简单应用示例2
- 致2016年——我走过的路,洒下的泪........
- 虚函数
- nyoj44 nyoj17 HDU1087 DP动规 连续字符串的和最大值 单调递增最长子序列 单调递增子序列最小个数 非连续最大递增子序列
- UVALive 7148 LRIP(树分治+STL)
- ios隐藏系统音量图标,并监听系统声音
- Nmap扫描原理与用法
- python profile
- Linux下MOOS编程(以应急程序为例)