Skip to main content
  1. Posts/

hdu 2873 Bomb Game(Sg函数)

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

hdu 2873题目链接

题意:n*m个格子,有若干炸弹。对于在第一行或者第一列的炸弹,爆炸后会到那一行或者那一列的更前面(总的来说就是更靠近左上角)的位置。对于其他位置的炸弹,爆炸后会生成两个炸弹,分别到那一行的更前面或者那 一列的更前面。问先手是否有必赢策略。

思路: 不会做2333 参考了 参考博客1 参考博客2

大概明白了一点。整个游戏可以分为若干个炸弹的游戏的和,而实际上一个不在边界行或者列的炸弹,依然可以继续分,分成两个炸弹的和。而位于(i.j)的炸弹,分成两个炸弹的和,有(i-1)*(j-1)种方案(这个不重要2333)

处于边界行或者列的点的sg值我们是可以知道的。。因为规则单一。。和移动等价。。

然后根据边界来进一步处理一般的情况。。

有点类似dp的思想。。。?

 1/* ***********************************************
 2Author :111qqz
 3Created Time :2016年07月23日 星期六 04时52分16秒
 4File Name :code/hdu/2873.cpp
 5************************************************ */
 6#include <cstdio>
 7#include <cstring>
 8#include <iostream>
 9#include <algorithm>
10#include <vector>
11#include <queue>
12#include <set>
13#include <map>
14#include <string>
15#include <cmath>
16#include <cstdlib>
17#include <ctime>
18#define fst first
19#define sec second
20#define lson l,m,rt<<1
21#define rson m+1,r,rt<<1|1
22#define ms(a,x) memset(a,x,sizeof(a))
23typedef long long LL;
24#define pi pair < int ,int >
25#define MP make_pair
26using namespace std;
27const double eps = 1E-8;
28const int dx4[4]={1,0,0,-1};
29const int dy4[4]={0,-1,1,0};
30const int inf = 0x3f3f3f3f;
31const int N=55;
32int n,m;
33int sg[N][N];
34bool vis[N*N];
35char maze[N][N];
36int px[N],py[N];
37void sg_init()
38{
39    ms(sg,0);
40    for ( int i = 0 ; i < N ; i++) //在边界的只能往一个方向生成炸弹,和移动了炸弹等价。
41	sg[i][0]=sg[0][i]=i;                       //还是0based好一点。。。这样(1,1)点的sg值自然就是0了。。。
42    for ( int i1 = 1 ; i1 < N ; i1++)
43	for ( int i2 = 1 ; i2 < N ; i2++)
44	{
45	    ms(vis,false);
46	    for ( int j1 =  0 ;  j1 < i1 ; j1++)
47		for ( int j2 = 0 ; j2 < i2 ; j2++)
48		    vis[sg[i1][j2]^sg[j1][i2]] = true;   //注意sg函数的变化规则。。其实是把一次爆炸考虑成两个爆炸的叠加,所以异或了。
49	    for ( int k = 0 ; ; k++)
50		if (!vis[k])
51		{
52		    sg[i1][i2] = k;
53		    break;
54		}
55	}
56}
57int main()
58{
59	#ifndef  ONLINE_JUDGE
60	freopen("code/in.txt","r",stdin);
61  #endif
62	sg_init();
63//or ( int i = 0 ; i <= 10 ; i++)
64//   for ( int j = 0 ; j <= 10 ; j++)
65//cout<<"i:"<<i<<" j:"<<j<<" sgg[i][j]:"<<sg[i][j]<<endl;
66	while (~scanf("%d%d",&n,&m))
67	{
68	    if (n==0&&m==0) break;
69	    for ( int i = 0 ; i < n ; i++) scanf("%s",maze[i]);
70	    int sum  =  0 ;
71	    for ( int i = 0 ; i  < n ; i++)
72		for ( int j = 0 ; j < m ; j++)
73		    if (maze[i][j]=='#')
74		    {
75			    int tmp = sg[i][j];
76			    sum ^= tmp;
77		    }
78	    if  (sum)
79	    {
80		puts("John");
81	    }
82	    else
83	    {
84		puts("Jack");
85	    }
86	}
87  #ifndef ONLINE_JUDGE
88  fclose(stdin);
89  #endif
90    return 0;
91}

Related

hdu 2509 Be the Winner (anti-sg,sg函数,sj定理)

hdu2509题目链接 题意:??? 思路:同1907 1/* *********************************************** 2Author :111qqz 3Created Time :2016年07月23日 星期六 04时41分38秒 4File Name :code/hdu/2509.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 41 while (~scanf("%d",&n)) 42 { 43 int sum = 0; 44 int cnt = 0 ; 45 for ( int i = 1 ; i <= n ; i++) 46 { 47 int x; 48 scanf("%d",&x); 49 sum^=x; 50 if (x>1) cnt++; 51 } 52 if ((sum==0&&cnt==0)||(sum>0&&cnt>0)) 53 { 54 puts("Yes"); 55 } 56 else 57 { 58 puts("No"); 59 } 60 } 61 62 #ifndef ONLINE_JUDGE 63 fclose(stdin); 64 #endif 65 return 0; 66}

hdu 1730 Northcott Game (二维sg函数)

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