• 「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;
    }
    
  • 相关阅读:
    signal(SIGCHLD, SIG_IGN)和signal(SIGPIPE, SIG_IGN);
    关于pthread_cond_wait使用while循环判断的理解
    linux的sleep()和usleep()的使用和区别
    C中结构体的存储分配
    扯扯python的多线程的同步锁 Lock RLock Semaphore Event Condition
    线程属性的初始化以及销毁
    Mysql数据库一个表字段中存了id,并以逗号分隔,id对应的详细信息在另一个表中
    sqlyog 注册码
    Oracle 12C卸载图文教程
    Oracle12c Release1安装图解(详解)
  • 原文地址:https://www.cnblogs.com/lizbaka/p/10520853.html
Copyright © 2020-2023  润新知