zoukankan      html  css  js  c++  java
  • 「Luogu4363/BZOJ5248」[九省联考2018]一双木棋chess

    「Luogu4363/BZOJ5248」[九省联考2018]一双木棋chess

    学校省选模拟居然拿九省联考来考

    然而我还是(toospace young),搞不懂什么叫最优

    让二者的答案最接近可以拿到(25)分的好成绩


    problem

    Solution

    首先可以知道菲菲想要最大化(ans=Ansa-Ansb),牛牛想要最小化

    那么我们可以用对抗搜索大力爆搜

    可以拿到50分

    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    template <typename T> void read(T &t)
    {
        t=0;int f=0;char c=getchar();
        while(!isdigit(c)){f|=c=='-';c=getchar();}
        while(isdigit(c)){t=t*10+c-'0';c=getchar();}
        if(f)t=-t;
    }
    
    const int maxn=15,maxm=15;
    int n,m;
    int A[maxn][maxm],B[maxn][maxm];
    int ocr[maxn][maxm];
    
    int dfs(int step)
    {
        if(step==n*m+1)
            return 0;
        int re=0;
        if(step&1)re=-0x3f3f3f3f;
        else re=0x3f3f3f3f;
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=m;++j)
                if(!ocr[i][j] && ocr[i-1][j] && ocr[i][j-1])
                {
                    ocr[i][j]=1;
                    if(step&1)re=max(re,dfs(step+1)+A[i][j]);
                    else re=min(re,dfs(step+1)-B[i][j]);
                    ocr[i][j]=0;
                }
        return re;
    }
    
    int main()
    {
        read(n);read(m);
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=m;++j)
                read(A[i][j]);
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=m;++j)
                read(B[i][j]);
        for(register int i=0;i<=n;++i)ocr[i][0]=1;
        for(register int i=0;i<=m;++i)ocr[0][i]=1;
        printf("%d",dfs(1));
        return 0;
    }
    

    显然这个东西可以记忆化一下

    (map)存一下棋盘的哈希值,吸氧的情况下是能A掉的

    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <map>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    template <typename T> void read(T &t)
    {
        t=0;int f=0;char c=getchar();
        while(!isdigit(c)){f|=c=='-';c=getchar();}
        while(isdigit(c)){t=t*10+c-'0';c=getchar();}
        if(f)t=-t;
    }
    
    const int maxn=15,maxm=15;
    
    int n,m;
    int A[maxn][maxm],B[maxn][maxm];
    int ocr[maxn][maxm];
    map<ull,int> rec;
    
    ull Hash()
    {
        ull re=0;
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=m;++j)
                re=re*3ull+ocr[i][j];
        return re;
    }
    
    int dfs(int step)
    {
        if(step==n*m+1)
            return 0;
        int re=0;
        ull h=Hash();
        if(rec.find(h)!=rec.end())
            return rec[h];
        if(step&1)re=-0x3f3f3f3f;
        else re=0x3f3f3f3f;
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=m;++j)
                if(!ocr[i][j] && ocr[i-1][j] && ocr[i][j-1])
                {
                    ocr[i][j]=1;
                    if(step&1)re=max(re,dfs(step+1)+A[i][j]);
                    else re=min(re,dfs(step+1)-B[i][j]);
                    ocr[i][j]=0;
                }
        return rec[h]=re;
    }
    
    int main()
    {
        read(n);read(m);
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=m;++j)
                read(A[i][j]);
        for(register int i=1;i<=n;++i)
            for(register int j=1;j<=m;++j)
                read(B[i][j]);
        for(register int i=0;i<=n;++i)ocr[i][0]=1;
        for(register int i=0;i<=m;++i)ocr[0][i]=1;
        printf("%d",dfs(1));
        return 0;
    }
    

    经过百度一下之后,发现此类对抗搜索还有一种优化,叫做(Alpha-Beta)优化

    在此仅放上介绍链接,不再赘述

    对于此题,我们如果使用(Alpha-Beta)优化,也能获得70分的成绩

    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    template <typename T> void read(T &t)
    {
    	t=0;int f=0;char c=getchar();
    	while(!isdigit(c)){f|=c=='-';c=getchar();}
    	while(isdigit(c)){t=t*10+c-'0';c=getchar();}
    	if(f)t=-t;
    }
    
    const int maxn=15,maxm=15;
    
    int n,m;
    int A[maxn][maxm],B[maxn][maxm];
    int ocr[maxn][maxm];
    
    const int inf=0x3f3f3f3f;
    
    
    int dfs(int step,int alpha,int beta,int nowa,int nowb)
    {
    	if(step==n*m+1)
    		return nowa-nowb;
    	if(step&1)
    	{
    		for(register int i=1;i<=n;++i)
    			for(register int j=1;j<=m;++j)
    				if(!ocr[i][j] && ocr[i-1][j] && ocr[i][j-1])
    				{
    					ocr[i][j]=1;
    					alpha=max(alpha,dfs(step+1,alpha,beta,nowa+A[i][j],nowb));
    					ocr[i][j]=0;
    					if(alpha>=beta)return alpha;
    				}
    		return alpha;
    	}
    	else
    	{
    		for(register int i=1;i<=n;++i)
    			for(register int j=1;j<=m;++j)
    				if(!ocr[i][j] && ocr[i-1][j] && ocr[i][j-1])
    				{
    					ocr[i][j]=1;
    					beta=min(beta,dfs(step+1,alpha,beta,nowa,nowb+B[i][j]));
    					ocr[i][j]=0;
    					if(alpha>=beta)return beta;
    				}
    		return beta;
    	}
    }
    
    int main()
    {
    	read(n);read(m);
    	for(register int i=1;i<=n;++i)
    		for(register int j=1;j<=m;++j)
    			read(A[i][j]);
    	for(register int i=1;i<=n;++i)
    		for(register int j=1;j<=m;++j)
    			read(B[i][j]);
    	for(register int i=0;i<=n;++i)ocr[i][0]=1;
    	for(register int i=0;i<=m;++i)ocr[0][i]=1;
    	printf("%d",dfs(1,-inf,inf,0,0));
    	return 0;
    }
    
  • 相关阅读:
    Windows Server 2008取消登录前的Ctrl+Alt+Delete组合键操作
    Kali Linux远程连接Windows服务器
    Kali Linux虚拟机安装完整安装过程及简单配置(视频)
    Kali Linux中下载工具Axel的安装和使用
    2017年Kali Linux更新源
    解决VMware虚拟机报错“无法连接MKS:套接字连接尝试次数太多,正在放弃”
    .deb软件包的安装和软件的卸载
    解决C语言程序报错:return type defaults to‘int’
    解决BackBox中Fcitx输入法中文输入状态下不显示候选词框的问题
    导航狗信息导航网站首页源代码(2017年11月03日版)
  • 原文地址:https://www.cnblogs.com/lizbaka/p/10520853.html
Copyright © 2011-2022 走看看