bzoj千题计划307:bzoj5248: [2018多省省队联测]一双木棋

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj千题计划307:bzoj5248: [2018多省省队联测]一双木棋相关的知识,希望对你有一定的参考价值。

https://www.lydsy.com/JudgeOnline/problem.php?id=5248

 

先手希望先手得分减后手得分最大,后手希望先手得分减后手得分最小

棋盘的局面一定是阶梯状,且从上往下递减

可以将轮廓线作为状态,记忆化搜索

用n个数表示一个状态,第i个数表示第i行放了几个

记忆的状态表示当棋盘为这个状态时,接下来再下的最有解

记忆化搜索节省的是接下来再下的时间

 

#include<map>
 
#include<cstdio>
 
#include<cstring>
 
#include<iostream>
 
#include<algorithm>
 
   
 
#define N 11
 
    
 
using namespace std;
 
   
 
int n,m;
 
   
 
int a[N][N],b[N][N];
 
   
 
struct node
 
{
 
    int v[N];
 
    node()
 
    {
 
        memset(v,0,sizeof(v));
 
    }
 
    bool operator < (node p) const
 
    {
 
        for(int i=1;i<=n;++i)
 
            if(v[i]<p.v[i]) return true;
 
            else if(v[i]>p.v[i]) return false;
 
    }
 
};
 
map<node,int>mp;
 
   
 
int dfs(node now,bool who)
 
{
 
    if(mp.find(now)!=mp.end()) return mp[now];
 
    int i;
 
    for(i=1;i<=n;++i)
 
        if(now.v[i]<m) break;
 
    if(i>n) return 0;
 
    int s;
 
    if(!who) s=-2e9;
 
    else s=2e9;
 
    for( i=1;i<=n;++i)
 
         if(now.v[i]!=m && (now.v[i]<now.v[i-1] || i==1))
 
         {
 
             now.v[i]++;
 
             if(!who) s=max(s,dfs(now,who^1)+a[i][now.v[i]]);
 
             else s=min(s,dfs(now,who^1)-b[i][now.v[i]]);
 
             now.v[i]--;
 
        }
 
    return mp[now]=s;
 
}
 
   
 
int main()
 
{
 
 //  freopen("data.in","r",stdin);
 
    scanf("%d%d",&n,&m);
 
    for(int i=1;i<=n;++i)
 
         for(int j=1;j<=m;++j)
 
             scanf("%d",&a[i][j]);
 
    for(int i=1;i<=n;++i)
 
         for(int j=1;j<=m;++j)
 
             scanf("%d",&b[i][j]);
 
    node now;
 
    printf("%d",dfs(now,0));
 
}

 

以上是关于bzoj千题计划307:bzoj5248: [2018多省省队联测]一双木棋的主要内容,如果未能解决你的问题,请参考以下文章

bzoj千题计划200:bzoj3106: [cqoi2013]棋盘游戏

bzoj千题计划214:bzoj3589: 动态树

bzoj千题计划197:bzoj4247: 挂饰

bzoj千题计划118:bzoj1028: [JSOI2007]麻将

bzoj千题计划165:bzoj5127: 数据校验

bzoj千题计划144:bzoj1176: [Balkan2007]Mokia