「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;
}
原文地址:https://www.cnblogs.com/lizbaka/p/10520853.html