zoukankan      html  css  js  c++  java
  • P4363 [九省联考2018]一双木棋

    题面

    这种搜索要把后继状态都跑出来之后取Min/Max

    也就是回溯的时候进行操作

    记得用hash进行记忆化(用map不开O2会TLE)

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<map>
    #define rg register
    #define max(x,y) (x)<(y)?(y):(x)
    #define min(x,y) (x)>(y)?(y):(x)
    using namespace std;
    int n,m,A[11][11],B[11][11],ri[11];//ri[]:每行向右延伸到了多少
    map<long long,int>dp;
    inline int read()
    {
        rg int save=0,w=1;rg char q=getchar();
        while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
        while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
        return save*w;
    }
    inline long long zip()//算出hash值
    {
        rg long long hash=0;
        for(rg int i=1;i<=n;++i)hash=(hash<<3)+(hash<<1)+hash+ri[i];
        return hash;
    }
    inline void recover(rg long long hash)//把状态解析出来
    {
        for(rg int i=n;i>=1;--i)ri[i]=hash%11,hash/=11;
    }
    int dfs(rg long long hash,rg bool b)//当前状态为hash,是谁下子(b==1为菲菲,b==0为牛牛)
    {
        rg int ans=((!b)?2147483647:-2147483647),i;
        if(dp[hash])return ((dp[hash]==-1)?0:dp[hash]);//如果该状况已经拓展过了,把记忆化的值返回即可
        //且因为A数组与B数组相加减的答案可能为0,而dp[]需要记录答案,所以当答案为0时,赋给dp[]的值为-1
        recover(hash);
        for(i=1;i<=n;++i)//枚举在哪一行向右走
        {
            if(ri[i]<ri[i-1])
            {
                ri[i]++;
                rg int behind=dfs(zip(),!b);//回溯回来的答案为behind
                if(b)ans=max(ans,behind+A[i][ri[i]]);//菲菲尽量使差变大  (差:菲菲-牛牛)
                else ans=min(ans,behind-B[i][ri[i]]);//牛牛尽量使差变小
                ri[i]--;//回溯,试着走别的点
            }
        }
        if(ans==((!b)?2147483647:-2147483647))ans=0;
        dp[hash]=(!ans)?-1:ans;
        return ans;
    }
    int main()
    {
        n=read(),m=read();
        rg int i,j;
        for(i=1;i<=n;++i)
            for(j=1;j<=m;++j)
                A[i][j]=read();
        for(i=1;i<=n;++i)
            for(j=1;j<=m;++j)
                B[i][j]=read();
    //    Take me to your heart, take me to your soul, give me your hand and hold me.
        ri[0]=m;
        printf("%d
    ",dfs(0,1));
        return 0;
    }
     
  • 相关阅读:
    Java 中String、StringBuffer、StringBuilder的差别
    [转载]StringBuffer versus String
    二维数组的连续子数组的最大和
    一位数组的最大和
    js中常见的去重方式
    魅族2016Java互联网方向其中一道笔试题--青蛙跳台阶问题
    美团在线编程2016--最大差值
    [转载]MySQL开发中常用的查询语句总结
    实现字符串全排列
    笔试题---最大子序列和
  • 原文地址:https://www.cnblogs.com/c-wen/p/9383788.html
Copyright © 2011-2022 走看看