zoukankan      html  css  js  c++  java
  • bzoj5248 [2018多省省队联测]一双木棋

    Description

    菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手。棋局开始时,棋盘上没有任何棋子,
    两人轮流在格子上落子,直到填满棋盘时结束。落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且
    这个格子的左侧及上方的所有格子内都有棋子。
    棋盘的每个格子上,都写有两个非负整数,从上到下第i行中从左到右第j列的格子上的两个整数记作Aij、Bij。在
    游戏结束后,菲菲和牛牛会分别计算自己的得分:菲菲的得分是所有有黑棋的格子上的Aij之和,牛牛的得分是所
    有有白棋的格子上的Bij的和。
    菲菲和牛牛都希望,自己的得分减去对方的得分得到的结果最大。现在他们想知道,在给定的棋盘上,如果双方都
    采用最优策略且知道对方会采用最优策略,那么,最终的结果如何
     
     

    Input

    第一行包含两个正整数n,m,保证n,m≤10。
    接下来n行,每行m个非负整数,按从上到下从左到右的顺序描述每个格子上的
    第一个非负整数:其中第i行中第j个数表示Aij。
    接下来n行,每行m个非负整数,按从上到下从左到右的顺序描述每个格子上的
    第二个非负整数:其中第i行中第j个数表示Bij
    n, m ≤ 10 , Aij, Bij ≤ 100000
     

    Output

    输出一个整数,表示菲菲的得分减去牛牛的得分的结果。
     

    Sample Input

    2 3
    2 7 3
    9 1 2
    3 7 2
    2 3 1

    Sample Output

    2
     
    考虑到n,m都很小
    所以我们可以维护轮廓线
    一开始我有一个naive的想法
    f[s]表示轮廓线状态为s时能取得的最优解,当前为先手取的话取max,后收取的话取min
    但是我发现这么做好像不对
    想了想改成f[s]表示轮廓线状态为s时能取得的最优解,当前为先手取的话取min,后收取的话取max
    发现还是不对
    这样做不能决定是谁的最优
    所以定义f[s]为状态为s时最多/最少还能得到的多少分数
    然后就可以瞎**dp了
    //%std
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    using namespace std;
    #define lovelive long long
    #define lc son[x][0]
    #define rc son[x][1]
    #define lowbit(x) (x&(-x))
    #define pt vc
    void read(int &x)
    {
      int p=1;
      x=0;
      char c=getchar();
      while(c<'0'||c>'9')
      {
        if(c=='-')
          p=-1;
        c=getchar();
      }
      while(c>='0'&&c<='9')
      {
          x=x*10+c-48;
          c=getchar();
      }
      x*=p;
    }
    map<lovelive,int>  sp;
    int f[200020];
    lovelive a[200020],tot;
    int A[2][11][11],n,m;
    void dfs(int i,lovelive j,lovelive lim,lovelive pre)
    {
      if(i==n)
      {
          pre=pre*lim+j;
          a[++tot]=pre;
          sp[pre]=tot;
        return; 
      }
      for(int k=0;k<=j;k++)
        dfs(i+1,j-k,lim,pre*lim+k);
    }
    lovelive pw[20];
    bool calc(lovelive x)
    {
      int sum=m; 
      int now=0;
      for(int j=0;j<n;j++)
      {
          sum-=x%(m+1);
          now^=sum;
          x/=(m+1);
      }
      return now&1;
    }
    int main()
    {
    //  freopen("chess.in","r",stdin);
    //  freopen("chess.out","w",stdout);
      int now=0,sum;
      lovelive x,y,tmp;
      read(n);read(m);
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          read(A[0][i][j]);
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          read(A[1][i][j]),A[1][i][j]*=-1;
      pw[0]=1;
      for(int i=1;i<=n;i++)
        pw[i]=pw[i-1]*(lovelive)(m+1);
      dfs(0,m,m+1,0);
      for(int i=1;i<=tot;i++)
      {
        if(!calc(a[i]))
          f[i]=-1e9;
        else
          f[i]=1e9;
      }
      f[1]=0;
      for(int i=1;i<=tot;i++)
      {
    //    if(f[i]!=0)
    //      i--,i++;
          x=y=a[i];
        now=calc(a[i]);
        sum=m;
          for(int j=0;j<n;j++)
          {
            sum-=x%(m+1);
    //        if(y-pw[j]+pw[j+1]==23579400)
    //          i--,i++;
            if(x%(m+1)!=0)
            {
                if(now)
                f[sp[y-pw[j]+pw[j+1]]]=max(f[sp[y-pw[j]+pw[j+1]]],f[i]+A[now][j+1][sum+1]);
              else
                f[sp[y-pw[j]+pw[j+1]]]=min(f[sp[y-pw[j]+pw[j+1]]],f[i]+A[now][j+1][sum+1]);
            }
            x/=(m+1);
        }
      }
      cout<<f[sp[m*pw[n]]]<<"
    ";
      return 0;
    } 
    /*
    2 3
    2 7 3
    9 1 2
    3 7 2
    2 3 1
    
    10 10
    0 0 1 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0
    
    */ 
    View Code
  • 相关阅读:
    Windows Server 2003 SP2(32位) 中文版 下载地址 光盘整合方法
    用Recycle()方法对Java对象的重要性
    Lotus中千奇百怪的 $$
    Developing a simple application using steps "User Decision" and "Mail"(1) 沧海
    沟通中的情绪管理(演讲稿) 沧海
    人只有在压力之下,才可能成功,没做一件事,都必须成功,不许言败 沧海
    什么是IDOC,以及IDOC的步骤 沧海
    VS2008 Professional Edition CHS中的deffactory.dat读取错误 沧海
    Including custom text in the step "User Decision" 沧海
    SAP Upgrade Strategy 沧海
  • 原文地址:https://www.cnblogs.com/NicoDafaGood/p/8868190.html
Copyright © 2011-2022 走看看