UVALive 6470 Chomp --记忆化搜索

题意:给一个只有三行的方块阵(横向最多100个),然后p,q,r分别代表第1,2,3层的方格数,两人轮流去掉一个格子,此时这个格子的右上方都会被去掉,面临只剩最左下角的一个格子的状态的人输,问先手能否赢,要赢得话应该取哪个方格。

解法:记忆化搜索,设dp[p][q][r]表示第1,2,3层方格数分别为p,q,r的输赢状态,0为输,1为赢,X[][][],Y[][][]分别表示其该取的方格坐标。每次求dp[p][q][r]时,枚举能达到的状态,如果这些状态的输赢值有一个为输,则此状态一定为赢,返回1,并记录好坐标,如果没有一个为输,则此状态为输。

初始值:

dp[1][0][0] = 0;

dp[1][1][0] = 1,X[1][1][0] = 1,Y[1][1][0] = 2;

dp[2][0][0] = 1,X[2][0][0] = 2,Y[2][0][0] = 1;

注意初始状态一定要最原始化,不要添加诸如只有最底层并且有n个,dp[n][0][0] = 1等的状态,因为不一定要这样取,也可能该行一个一个的取。

记忆化搜索加快速度

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <algorithm>

using namespace std;

#define N 1007

#define M 33



int dp[104][104][104];

int X[104][104][104],Y[104][104][104];

int kx,ky;



void init()

{

    memset(dp,-1,sizeof(dp));

    memset(X,0,sizeof(X));

    memset(Y,0,sizeof(Y));

    //dp[0][0][0] = 1;

    dp[1][0][0] = 0;            //写出最基本的几个即可,不要乱加

    dp[1][1][0] = 1,X[1][1][0] = 1,Y[1][1][0] = 2;

    //dp[1][1][1] = 1,X[1][1][1] = 2,Y[1][1][1] = 1;

    //for(int i=2;i<=100;i++)

    dp[2][0][0] = 1,X[2][0][0] = 2,Y[2][0][0] = 1;

}



int DP(int p,int q,int r)

{

    if(dp[p][q][r] != -1)

        return dp[p][q][r];

    int i;

    for(i=r;i>=1;i--)   //顶层

    {

        if(DP(p,q,i-1) == 0)

        {

            X[p][q][r] = i;

            Y[p][q][r] = 3;

            return dp[p][q][r] = 1;

        }

    }

    for(i=q;i>=1;i--)    //中层

    {

        if(DP(p,i-1,min(r,i-1)) == 0)

        {

            X[p][q][r] = i;

            Y[p][q][r] = 2;

            return dp[p][q][r] = 1;

        }

    }

    for(i=p;i>=2;i--)   //底层,注意>=2而不是1

    {

        if(DP(i-1,min(q,i-1),min(r,i-1)) == 0)

        {

            X[p][q][r] = i;

            Y[p][q][r] = 1;

            return dp[p][q][r] = 1;

        }

    }

    return dp[p][q][r] = 0;

}



int main()

{

    int p,q,r,t,cs;

    scanf("%d",&t);

    init();

    while(t--)

    {

        scanf("%d%d%d%d",&cs,&p,&q,&r);

        if(DP(p,q,r))

            printf("%d W %d %d\n",cs,X[p][q][r],Y[p][q][r]);

        else

            printf("%d L\n",cs);

    }

    return 0;

}
View Code

你可能感兴趣的:(live)