zoukankan      html  css  js  c++  java
  • 【九省联考2018】一双木棋

    题面

    https://www.luogu.org/problem/P4363

    题解

    很套路的$hash$状态$+dp$。

    可知棋子形成的形状一定是一个连续的倒楼梯形(楼梯向右延伸的长度可以不连续,但一定单调)

    $hash$轮廓就行了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #define ri register int
    #define N 11
    #define LL long long
    #define INF 1000000007
    #define mod 1233107
    using namespace std;
    int a[N][N],b[N][N];
    LL pow[N];
    int n,m;
    vector<int>f[mod];
    vector<LL>g[mod];
    
    int dfs(LL x) {
      int ln[N];
      int yx=x%mod;
      for (ri i=0;i<g[yx].size();i++) if (g[yx][i]==x) return f[yx][i];
      g[yx].push_back(x);
      f[yx].push_back(0);
      int tl=f[yx].size()-1;
      int tot=0,opt,ret;
      LL tx=x,nx;
      for (ri i=n;i>=1;i--) {
        ln[i]=x/pow[i];
        x%=pow[i];
      }
      ln[0]=m+1;
      for (ri i=1;i<=n;i++) tot+=ln[i];
      if (tot==n*m) return 0;
      if (tot%2==0) opt=1; else opt=0;
        
      if (opt) ret=-INF; else ret=INF;
      for (ri i=1;i<=n;i++) if (ln[i-1]>ln[i] && ln[i]+1<=m) {
        nx=tx+pow[i];
        if (opt) {
          int t=dfs(nx);
          if (a[i][ln[i]+1]+t>ret) ret=a[i][ln[i]+1]+t;
        }
        else {
          int t=dfs(nx);
          if (-b[i][ln[i]+1]+t<ret) ret=-b[i][ln[i]+1]+t;
        }
      }
      return f[yx][tl]=ret;
    }
    
    int main(){
      cin>>n>>m;
      for (ri i=1;i<=n;i++) 
        for (ri j=1;j<=m;j++) cin>>a[i][j];
      for (ri i=1;i<=n;i++)
        for (ri j=1;j<=m;j++) cin>>b[i][j];
      pow[1]=1LL;
      for (ri i=2;i<=n;i++) pow[i]=pow[i-1]*11LL;
      printf("%d
    ",dfs(0));
    }
  • 相关阅读:
    Ubuntu 16 安装ElasticSearch
    二叉树
    归并排序
    快速排序
    Git、Github使用
    445. 两数相加 II
    141. 环形链表
    92. 反转链表 II
    19. 删除链表的倒数第N个节点
    2. 两数相加
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11426246.html
Copyright © 2011-2022 走看看