• 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
  • 相关阅读:
    Codeforces Round #296 (Div. 2B. Error Correct System
    实验十二 图的建立与遍历
    1561: (More) Multiplication
    1562: Fun House
    hdu 2203 亲和串
    hdu 3549Flow Problem
    poj 2182 Lost Cows
    poj 3468A Simple Problem with Integers
    hdu1698 Just a Hook
    栈和队列的面试题Java实现
  • 原文地址:https://www.cnblogs.com/NicoDafaGood/p/8868190.html
Copyright © 2020-2023  润新知