zoukankan      html  css  js  c++  java
  • 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));
     
    }
  • 相关阅读:
    【递归】拆分自然数
    HDOJ3068最长回文
    博弈论——尼姆博奕
    vijos P1047最小公倍数
    Eular质数筛法-hiho一下 第九十三周
    hdoj-5652 India and China Origins二分+bfs
    hdoj-1166排兵布阵 简单的树状数组
    hdoj-5641 king's phone
    hdoj-1548简单的bfs题目
    命令中"|"的意义
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8946872.html
Copyright © 2011-2022 走看看