洛谷 P4363 [九省联考2018]一双木棋chess 题解

题目链接:https://www.luogu.org/problemnew/show/P4363

分析:

首先博弈,然后考虑棋盘的规则,因为一个子在落下时它的上面和左面都已经没有空位了,所以棋子的右下的轮廓线一定是个凸包,更具体地,从棋盘的左下沿着棋盘边界或棋子轮廓线走到棋盘右上,所走的路径一定只有向上和向右两种。

代码:

#include<cstdio>
using namespace std;
const int maxn=25,N=1<<20,INF=0x3f3f3f3f;
int f[N],n,m,nm,c[2][maxn][maxn];bool vis[N];
void Max(int &x,int y)
{
    if(x<y)
        x=y;
    
}
int Run(int now,bool rt)
{
    if(vis[now])
    return -f[now];
    vis[now]=true;
    int &ans=f[now],k=0,i,j,cur=now,cnt=0;
    ans=-INF;
    for(k=0;now&&(k<nm);k++,cnt+=i)
    {
        i=now&1,now>>=1,j=now&1;
        if(i&&!j)
            Max(ans,Run(cur^(3<<k),!rt)+c[rt][k+1-cnt][m-cnt]);
    }
    return -ans;
}
int main()
{
    int i,j;
    scanf("%d%d",&n,&m),nm=n+m-1;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&c[0][i][j]);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&c[1][i][j]);
    vis[((1<<m)-1)<<n]=true,printf("%d\n",-Run((1<<m)-1,0));
    return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShineEternal

觉得好就给点鼓励呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值