↓ Skip to main content
  1. Posts/

hdu 1730 Northcott Game (二维sg函数)

·693 words·2 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

hdu 1730

题意:n行格子,每行m个,每行有一黑一白两个棋子,给定初始位置,先手执黑棋,后手执白棋,每次可以在同一行内向左移动,不能超过边界,且不能越过对方的棋子,同一个格子只能有一个棋子。问先手是否必赢。

思路:可以看成n个独立的游戏的 叠加。。。所以最后异或和一下就好。。

我们来求sg函数。。。一开始的是想把点对hash成一个数。。。然后发现其实没必要。。。直接二维就好了。。

由于初始化的时候要考虑最大。。。所以sg函数的值会有一个便宜。。。和设定N有关。。减去偏移就好了。。。(我的代码里这个偏移是11026)

1A蛤蛤蛤

代码实现
  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年07月22日 星期五 21时01分19秒
  4File Name :code/hdu/1730.cpp
  5************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int inf = 0x3f3f3f3f;
 33const int N=2E2+7;
 34bool vis[N*N];
 35int sg[N][N];
 36int n,m;
 37
 38void sg_init(int m)
 39{
 40    ms(sg,0);
 41
 42    for ( int i1 = 1 ; i1 <= m ; i1++)
 43	for ( int i2 = 1 ; i2 <= m ; i2++)
 44	{
 45	    if (i1==i2) continue ;  // 棋子不能在同一个位置?
 46	    ms(vis,false);
 47
 48	    int x = i1;
 49	    int y = i2;
 50
 51	    if ( x<y )
 52	    {
 53		for ( int j = x+1 ; j <=y-1;  j++)
 54		    vis[sg[x][j]] = true;
 55
 56		for ( int j = 1 ; j <= x-1 ; j++)
 57		    vis[sg[j][y]] = true;
 58	    }
 59	    else
 60	    {
 61		for ( int j = y + 1 ; j  <= x-1 ; j++)
 62		    vis[sg[j][y]] = true;
 63
 64		for ( int j =1 ; j <= y-1 ; j++)
 65		    vis[sg[x][j]] = true;
 66	    }
 67
 68	    for ( int j1  = 1 ;  j1 <= m ; j1++ )
 69		for ( int j2 = 1 ; j2 <= m ; j2++)
 70		    if (!vis[j1*m+j2])
 71		    {
 72			//cout<<"acccc"<<endl;
 73			sg[i1][i2] = j1*m+j2;
 74			break;
 75		    }
 76	}
 77}
 78int main()
 79{
 80	#ifndef  ONLINE_JUDGE
 81	freopen("code/in.txt","r",stdin);
 82  #endif
 83
 84	sg_init(105);
 85
 86//	for ( int i =  0 ;i <= 10 ; i++)
 87//	    for ( int j = 0  ; j <= 10 ; j++)
 88//		cout<<"i:"<<i<<" j:"<<j<<" "<<sg[i][j]<<endl;
 89	while (~scanf("%d%d",&n,&m))
 90	{
 91	    int sum = 0 ;
 92	    for ( int  i = 1 ; i <= n ; i++)
 93	    {
 94		int x,y;
 95		scanf("%d%d",&x,&y);
 96		int tmp = sg[x][y]-11026;
 97		sum^=tmp;
 98	    }
 99	    if (sum)
100	    {
101		puts("I WIN!");
102	    }
103	    else
104	    {
105		puts("BAD LUCK!");
106	    }
107	}
108
109
110  #ifndef ONLINE_JUDGE
111  fclose(stdin);
112  #endif
113    return 0;
114}

Related

hdu 1536 S-Nim (sg函数)

·350 words·1 min
hdu 1536题目链接 题意:还是若干堆石子,但是每次取的个数只能是集合S中有的数。。问是否必赢。。。 思路:sg函数。。。1A 代码实现 1/* *********************************************** 2Author :111qqz 3Created Time :2016年07月20日 星期三 23时32分48秒 4File Name :code/hdu/1536.cpp 5************************************************ */ 6 7#include <cstdio> 8#include <cstring> 9#include <iostream> 10#include <algorithm> 11#include <vector> 12#include <queue> 13#include <set> 14#include <map> 15#include <string> 16#include <cmath> 17#include <cstdlib> 18#include <ctime> 19#define fst first 20#define sec second 21#define lson l,m,rt<<1 22#define rson m+1,r,rt<<1|1 23#define ms(a,x) memset(a,x,sizeof(a)) 24typedef long long LL; 25#define pi pair < int ,int > 26#define MP make_pair 27 28using namespace std; 29const double eps = 1E-8; 30const int dx4[4]={1,0,0,-1}; 31const int dy4[4]={0,-1,1,0}; 32const int inf = 0x3f3f3f3f; 33const int N=1E4+7; 34int sg[N]; 35bool vis[N]; 36int ok[N]; 37int k,m; 38 39void sg_init() 40{ 41 ms(sg,0); 42 43 for ( int i = 1; i < N ; i++) 44 { 45 ms(vis,false); 46 for ( int j = 1 ; j <= k ; j++) 47 if (i-ok[j]>=0) vis[sg[i-ok[j]]] = true; 48 49 for ( int j = 0 ; ; j++) 50 if (!vis[j]) 51 { 52 sg[i] = j; 53 break; 54 } 55 } 56} 57int main() 58{ 59 #ifndef ONLINE_JUDGE 60 freopen("code/in.txt","r",stdin); 61 #endif 62 63 while (~scanf("%d",&k)) 64 { 65 if (k==0) break; 66 ms(ok,0); 67 for ( int i = 1 ; i <= k ; i++) scanf("%d",&ok[i]); 68 sg_init(); 69 scanf("%d",&m); 70// cout<<"m:"<<m<<endl; 71 while (m--) 72 { 73 int num; 74 scanf("%d",&num); 75 int sum = 0 ; 76 while (num--) 77 { 78 int x; 79 scanf("%d",&x); 80 sum^=sg[x]; 81 } 82 if (sum==0) printf("L"); 83 else printf("W"); 84 } 85 printf("\n"); 86 } 87 88 #ifndef ONLINE_JUDGE 89 fclose(stdin); 90 #endif 91 return 0; 92}

hdu 1848 Fibonacci again and again (sg函数)

·448 words·1 min
hdu 1848题目链接 题意:三堆石头,每次任选一堆取,取的石子数目必须是斐波那契数列中的数(1,2,3,5,8….)问先手是否有必赢策略。 思路:sg函数即可。。。。这次sg函数的优越性终于体现出来了。。。其他方法估计很难写吧。。

hdu 1850 Being a Good Boy in Spring Festival (nim游戏问必胜方案数,sg函数)

·422 words·1 min
hdu1850题目链接 题意:n堆石子。。每堆可以取任意多个。。。先取完的赢。。问先手能否赢。。能赢的话第一步有几种取法。。 思路:sg函数。。对于方案数,可以用nim游戏的结论。 以及。。sg函数。。如果走的步数是任意的。。也就是没有限制。。。那么sg[i] = i…此时也就退化成了一般的nim游戏。。。

hdu 1847 Good Luck in CET-4 Everybody! (巴什博奕,找规律||sg函数)

·635 words·2 mins
hdu1847题目链接 题意:n个石子,每次只能取2的幂次个。。。问先手是否有必赢策略。。。 思路:画n点p点。。。发现n为3的倍数的时候先手必输。。。否则先手必赢。。。 代码实现 1/* *********************************************** 2Author :111qqz 3Created Time :2016年07月20日 星期三 18时54分46秒 4File Name :code/hdu/1847.cpp 5************************************************ */ 6 7#include <cstdio> 8#include <cstring> 9#include <iostream> 10#include <algorithm> 11#include <vector> 12#include <queue> 13#include <set> 14#include <map> 15#include <string> 16#include <cmath> 17#include <cstdlib> 18#include <ctime> 19#define fst first 20#define sec second 21#define lson l,m,rt<<1 22#define rson m+1,r,rt<<1|1 23#define ms(a,x) memset(a,x,sizeof(a)) 24typedef long long LL; 25#define pi pair < int ,int > 26#define MP make_pair 27 28using namespace std; 29const double eps = 1E-8; 30const int dx4[4]={1,0,0,-1}; 31const int dy4[4]={0,-1,1,0}; 32const int inf = 0x3f3f3f3f; 33int n; 34int main() 35{ 36 #ifndef ONLINE_JUDGE 37 freopen("code/in.txt","r",stdin); 38 #endif 39 40 while (scanf("%d",&n)!=EOF) 41 { 42 if (n%3==0) 43 { 44 puts("Cici"); 45 } 46 else 47 { 48 puts("Kiki"); 49 } 50 } 51 52 #ifndef ONLINE_JUDGE 53 fclose(stdin); 54 #endif 55 return 0; 56} 也可以利用sg函数求解。。。 从这里我们可以看出,sg函数类似于母函数,本身并不是一类问题,而是一种求解问题的工具。

hdu 1849Rabbit and Grass(一维nim游戏,sg函数)

·1290 words·3 mins
Rabbit and Grass # **Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3058 Accepted Submission(s): 2261 ** Problem Description 大学时光是浪漫的,女生是浪漫的,圣诞更是浪漫的,但是Rabbit和Grass这两个大学女生在今年的圣诞节却表现得一点都不浪漫:不去逛商场,不去逛公园,不去和AC男约会,两个人竟然猫在寝食下棋…… 说是下棋,其实只是一个简单的小游戏而已,游戏的规则是这样的: 1、棋盘包含1*n个方格,方格从左到右分别编号为0,1,2,…,n-1; 2、m个棋子放在棋盘的方格上,方格可以为空,也可以放多于一个的棋子; 3、双方轮流走棋; 4、每一步可以选择任意一个棋子向左移动到任意的位置(可以多个棋子位于同一个方格),当然,任何棋子不能超出棋盘边界; 5、如果所有的棋子都位于最左边(即编号为0的位置),则游戏结束,并且规定最后走棋的一方为胜者。