• 【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)


    【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)

    题面

    BZOJ

    Description

    菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手。棋局开始时,棋盘上没有任何棋子,
    两人轮流在格子上落子,直到填满棋盘时结束。落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且
    这个格子的左侧及上方的所有格子内都有棋子。
    棋盘的每个格子上,都写有两个非负整数,从上到下第i行中从左到右第j列的格子上的两个整数记作Aij、Bij。在
    游戏结束后,菲菲和牛牛会分别计算自己的得分:菲菲的得分是所有有黑棋的格子上的Aij之和,牛牛的得分是所
    有有白棋的格子上的Bij的和。
    菲菲和牛牛都希望,自己的得分减去对方的得分得到的结果最大。现在他们想知道,在给定的棋盘上,如果双方都
    采用最优策略且知道对方会采用最优策略,那么,最终的结果如何

    Input

    第一行包含两个正整数n,m,保证n,m≤10。
    接下来n行,每行m个非负整数,按从上到下从左到右的顺序描述每个格子上的
    第一个非负整数:其中第i行中第j个数表示Aij。
    接下来n行,每行m个非负整数,按从上到下从左到右的顺序描述每个格子上的
    第二个非负整数:其中第i行中第j个数表示Bij
    n, m ≤ 10 , Aij, Bij ≤ 100000

    Output

    输出一个整数,表示菲菲的得分减去牛牛的得分的结果。

    Sample Input

    2 3

    2 7 3

    9 1 2

    3 7 2

    2 3 1

    Sample Output

    2

    题解

    考虑一下所谓的两个人都是走最优策略
    也就是对于第一个人,
    它一定从当前局面可以到达的所有局面中,选择一个最大的走。
    第二个人一定会从当前局面所有可以到达的局面中,选择一个最小的走。
    (这就是所谓的(min-max)搜索???或者叫对抗搜索??)

    考虑一下所有的状态,一定是一个从上往下的阶梯型
    因为(n,m<=10)
    所以我们可以用一个(n)位的(m+1)进制数把当前下完的轮廓给哈希一下。

    那么,对于一个局面,我们可以做记忆化搜索,
    我们只需要根据局面当前下子的是谁,决定这个状态是最大还是最小。这样用(map)压下当前所有状态,直接搜索即可。。

    要是让我考我肯定做不出来

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 15
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    const int Base=11;
    map<ll,int> M;
    int ln[MAX],n,m;
    int A[MAX][MAX],B[MAX][MAX];
    ll Hash(){ll ret=0;for(int i=1;i<=n;++i)ret=ret*Base+ln[i];return ret;}
    void UnHash(ll st){for(int i=n;i;--i)ln[i]=st%Base,st/=Base;}
    int Next(){int ret=0;for(int i=1;i<=n;++i)ret+=ln[i];return ret&1;}
    int dfs(ll st)
    {
    	if(M.count(st))return M[st];
    	UnHash(st);
    	int opt=Next(),ret=opt?1e9:-1e9;
    	for(int i=1;i<=n;++i)
    		if(ln[i-1]>ln[i])
    		{
    			ln[i]++;
    			ll now=Hash();
    			opt?ret=min(ret,dfs(now)-B[i][ln[i]]):ret=max(ret,dfs(now)+A[i][ln[i]]);
    			ln[i]--;
    		}
    	return M[st]=ret;
    }
    int main()
    {
    	n=read();ln[0]=m=read();
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			A[i][j]=read();
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			B[i][j]=read();
    	ll all=0;
    	for(int i=1;i<=n;++i)all=all*Base+m;
    	M[all]=0;
    	dfs(0);
    	printf("%d
    ",M[0]);
    	return 0;
    }
    
    
  • 相关阅读:
    Java appendReplacement 和 appendTail 方法
    UVA Mapping the Swaps
    oppo X907刷机包 COLOROS 1.0 正式版公布 安卓4.2.2
    MVC传递Model之TempData、ViewData、ViewBag差别及用途
    新加坡电视剧--幸福料理Spice Up每集剧情 Episodic Synopsis_wkh73_新浪博客
    七分食三分练,“七分食”希望解决的是健身人群的独特用餐需求
    基于Redis的BloomFilter算法去重
    砍高层“手脚”、中层“屁股”、基层“脑袋”……任正非管人用人之道竟是如此简单!
    (2)注码法的价值
    全球购 颂拓SUUNTO手表AMBIT3拓野3户外运动石英男表巅峰系列 巅峰蓝宝石心率 SS020673000【图片 价格 品牌 报价】-京东
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8729229.html
Copyright © 2020-2023  润新知