您的位置:首页 > 其它

组合博弈之SG入门

2016-08-06 12:53 393 查看
记录一个菜逼的成长。。

步骤1:将所有终结位置标记为必败点(P点);

步骤2: 将所有一步操作能进入必败点(P点)的位置标记为必胜点(N点)

步骤3:如果从某个点开始的所有一步操作都只能进入必胜点(N点) ,则将该点标记为必败点(P点) ;

步骤4: 如果在步骤3未能找到新的必败(P点),则算法终止;否则,返回到步骤2。

【HD1846】Brave Game

暴力SG表

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000;
int sg[maxn];
bool Hash[maxn];
void sg_solve(int n,int m)
{
memset(sg,0,sizeof(sg));
for( int j,i = 1; i <= n; i++ ){
memset(Hash,0,sizeof(Hash));
for( j = 1; j <= min(i,m); j++ ){
Hash[sg[i-j]] = 1;
}
for( j = 0; j <= n; j++ ){
if(!Hash[j])break;
}
sg[i] = j;
}
}
int main()
{
int T;scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
sg_solve(n,m);
printf("%s\n",sg
?"first":"second");
}
return 0;
}


【HD2147】kiki’s game

规律

#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
if(!n && !m)break;
printf("%s\n",n%2&&m%2?"What a pity!":"Wonderful!");
}
return 0;
}


【HD2188】悼念512汶川大地震遇难同胞——选拔志愿者

打SG表找规律

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10000 + 10;
int sg[maxn],Hash[maxn];
void sg_solve(int n,int m)
{
memset(sg,0,sizeof(sg));
for( int j,i = 1; i <= n; i++ ){
memset(Hash,0,sizeof(Hash));
for( j = 1; j <= min(i,m); j++ ){
Hash[sg[i-j]] = 1;
}
for( j = 0; j <= n; j++ ){
if(!Hash[j])break;
}
sg[i] = j;
}
}
int main()
{
int T;scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
if(n <= m){
printf("Grass\n");
}
else {
//sg_solve(n,m);
printf("%s\n",n%(m+1)?"Grass":"Rabbit");
}
}
return 0;
}


【HD2149】Public Sale

1. 如果 m <= n 直接输出 m 到 n的数;

2. 打sg表判断sg[m]是否为0 ,为0则直接输出none ;不为0 ,则转化为(m-x,n)的问题,所以从m往前扫描直到sg[i] = 0;

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1100 + 10;
int sg[maxn],Hash[maxn];
void sg_solve(int n,int m)
{
memset(sg,0,sizeof(sg));
for( int j,i = 1; i <= n; i++ ) {
memset(Hash,0,sizeof(Hash));
for( j = 1 ; j <= min(i,m); j++ ){
Hash[sg[i-j]] = 1;
}
for( j = 0; j <= n; j++ )
if(!Hash[j])break;
sg[i] = j;
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&m,&n)){
if(n >= m){
for( int i = m; i <= n; i++ ){
if(i == m)printf("%d",i);
else printf(" %d",i);
}
puts("");
}
else {
sg_solve(m,n);
if(!sg[m])printf("none\n");
else {
for( int i = m; i >= 0; i-- ){
if(!sg[i]){
printf("%d\n",m - i);
break;
}
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  博弈 SG 规律