日期游戏解题报告(对抗搜索的典型运用)

题目链接:http://acm.qust.edu.cn/problem.php?id=1005

典型的对抗搜索(对抗搜索是一种记忆化搜索,属于博弈论的范畴,若要了解更多关于对抗搜索的知识,请阅读刘汝佳的《算法竞赛入门经典训练指南》P400)。用f[y][m][d]表示在y 年 m 月d 日状态下,该操作者是否有必胜策略,g[y][m][d] 表示这一状态是否已经计算过。对于当前状态,搜索其下一状态是否有必胜策略:若有,则该状态没有必胜策略;反之则有必胜策略。

#include<stdio.h>
#include<cstring>
using namespace std;


bool f[2010][13][35],g[2010][13][35];
int a[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},   //a[0][i] 表示平年i 月的天数,a[1][i] 表示闰年i月的天数
                      {0,31,29,31,30,31,30,31,31,30,31,30,31}};


bool ping(int y)    //判断是否为平年
{
    if (y%100==0) return false;
    else
        if (y%4==0) return false;
    return true;
}


bool dfs(int y,int m,int d)    //对抗搜索
{
    int yy,mm,dd;


    if (y>2001) return false;
    if (g[y][m][d]) return f[y][m][d];
    if ((y==2001)&&(m==11)&&(d==4))
    {
        f[y][m][d]=false;
        g[y][m][d]=true;
        return f[y][m][d];
    }


    if (ping(y))  //平年
    {
        dd=(d%a[0][m])+1; mm=m; yy=y;    //天数+1
        if (dd==1) mm++;
        if (mm>12)
        {
            mm=1;
            yy++;
        }
        if (!g[yy][mm][dd])
        {
            f[yy][mm][dd]=dfs(yy,mm,dd);
            g[yy][mm][dd]=true;
            f[y][m][d]=(!f[yy][mm][dd]||f[y][m][d]);
        }
        else f[y][m][d]=(!f[yy][mm][dd]||f[y][m][d]);
        dd=d; mm=m+1; yy=y;    //月数+1
        if (mm>12)
        {
            mm=1;
            yy++;
        }
        if (dd<=a[0][mm])
        {
            if (!g[yy][mm][dd])
            {
                f[yy][mm][dd]=dfs(yy,mm,dd);
                g[yy][mm][dd]=true;
                f[y][m][d]=(!f[yy][mm][dd]||f[y][m][d]);
            }
            else f[y][m][d]=(!f[yy][mm][dd]||f[y][m][d]);
        }
    }
    else    //闰年
    {
        dd=(d%a[1][m])+1; mm=m; yy=y;   //天数+1
        if (dd==1) mm++;
        if (mm>12)
        {
            mm=1;
            yy++;
        }
        if (!g[yy][mm][dd])
        {
            f[yy][mm][dd]=dfs(yy,mm,dd);
            g[yy][mm][dd]=true;
            f[y][m][d]=(!f[yy][mm][dd]||f[y][m][d]);
        }
        else f[y][m][d]=(!f[yy][mm][dd]||f[y][m][d]);
        dd=d; mm=m+1; yy=y;     //月数+1
        if (mm>12)
        {
            mm=1;
            yy++;
        }
        if (dd<=a[1][mm])
        {
            if (!g[yy][mm][dd])
            {
                f[yy][mm][dd]=dfs(yy,mm,dd);
                g[yy][mm][dd]=true;
                f[y][m][d]=(!f[yy][mm][dd]||f[y][m][d]);
            }
            else f[y][m][d]=(!f[yy][mm][dd]||f[y][m][d]);
        }
    }


    return f[y][m][d];
}


int main()
{
    int i,t,y,m,d;


    scanf("%d",&t);
    for (i=0;i<t;i++)
    {
        memset(f,false,sizeof(f));
        memset(g,false,sizeof(g));
        scanf("%d%d%d",&y,&m,&d);
        f[y][m][d]=dfs(y,m,d);
        if (f[y][m][d]) printf("YES\n");
        else printf("NO\n");
    }


    return 0;
}

你可能感兴趣的:(日期游戏解题报告(对抗搜索的典型运用))