zoukankan      html  css  js  c++  java
  • S-Nim HDU 1536 博弈 sg函数

    S-Nim HDU 1536 博弈 sg函数

    题意

    首先输入K,表示一个集合的大小,之后输入集合,表示对于这对石子只能去这个集合中的元素的个数,之后输入 一个m表示接下来对于这个集合要进行m次询问,之后m行,每行输入一个n表示有n个堆,每堆有n1个石子,问这一行所表示的状态是赢还是输,如果赢输入W否则L。

    解题思路

    如果没有每次取石子个数的限制的话,那么仅仅需要把每堆石子的个数进行异或运算即可,如果结果不是1,那么先手赢,反之后手赢。

    但是这里对每次取石子的个数进行了限制,每次只能从几个数中进行选择,这是就需要SG函数来进行处理了。至于为什么要使用SG函数来进行处理这里没有写,详细可以参考这个博客博弈论 SG函数

    这里仅仅写了SG函数的两种写法:1是打表法,2是DFS法。

    代码实现

    //打表法实现
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e4+7;
    int sg[maxn];
    bool book[maxn];//这个需要用bool类型,如果改成int类型会超时,第一次遇到。
    int s[107];
    int k, m, l;
    void getsg(int n, int k)//n代表这堆石子最多有多少,k代表有多少种取的模式
    {
    	int i, j;
    	memset(sg, 0, sizeof(sg));
    	for(i=1; i<=n; i++)
    	{
    		memset(book, 0, sizeof(book));//每次有需要进行
    		for(j=1; j<=k && s[j]<=i; j++)
    			book[sg[i-s[j]]]=1;
    		for(j=0; ; j++)//查找里面第一个是0的
    			if(!book[j])
    			{
    				sg[i]=j;
    				break;
    			}
    	}
    }
    int main()
    {
    	while(scanf("%d",&k) && k)
    	{
    		for(int i=1; i<=k; i++)
    			scanf("%d",&s[i]);
    		sort(s+1, s+1+k);
    		getsg(maxn-7, k);
    		scanf("%d",&m);
    		while(m--)
    		{
    			scanf("%d", &l);
    			int tmp, ans=0;
    			while(l--)
    			{
    				scanf("%d", &tmp);
    				ans^=sg[tmp];
    			}
    			if(ans==0)
    				printf("L");
    			else
    				printf("W"); 
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=10050+7;
    int s[105];
    int SG[maxn];
    int k, m, l;
    int sg(int x)
    {
    	if(SG[x]!=-1) return SG[x];//记忆化搜索
    	bool book[105];
        memset(book, 0, sizeof(book));
    	for(int i=1; i<=k && x-s[i]>=0; i++)
    		book[sg(x-s[i])]=1; //寻找他的下面的所有状态
    	for(int i=0; i<105; i++) //找到第一个是0的位置
    		if(book[i]==0) return SG[x]=i;
    }
    
    int main()
    {
    	while(scanf("%d", &k) && k)
    	{
    		for(int i=1; i<=k; i++)
    			scanf("%d", &s[i]);
    		sort(s+1, s+1+k);
    		memset(SG, -1, sizeof(SG));
    		scanf("%d",&m);
    		while(m--)
    		{
    			scanf("%d", &l);
    			int tmp, ans=0;
    			for(int i=1;i<=l; i++)
    			{
    				scanf("%d", &tmp);
    				ans^=sg(tmp);
    			}
    			if(ans==0) printf("L");
    			else printf("W");
    		}
    		printf("
    ");
    	}
    	return 0;
     } 
    
    欢迎评论交流!
  • 相关阅读:
    poj 2352 Stars(线段树)
    poj 2029 Get Many Persimmon Trees
    .Net remoting 的解答,以及跟WebService的区别
    关于Xcode4.2中的release“不能”使用的理解
    委托的学习日志
    钩子是啥?以及用来说啥,是不是可以用来做即时通讯?
    C#后台程序与HTML页面中JS方法互调(功能类似于Ajax中的DWR)
    接触了一下项目管理系统软件:禅道项目管理软件、Bugfree
    将string变为int 的几种方法方法比较
    Hashtable、Dictionary、SortedDictionary、SortedList的比较应用
  • 原文地址:https://www.cnblogs.com/alking1001/p/11704461.html
Copyright © 2011-2022 走看看