zoukankan      html  css  js  c++  java
  • [BZOJ5248][2018九省联考]一双木棋

    题目描述

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

     

    Solution

    我们首先考虑放棋子的操作

    发现它一定放棋子的部分是一个联通块,不放棋子的是一个联通块

    所以 我们考虑怎么表示这个轮廓

    分析一下 N,M<=10 ?!

    状态压缩?大爆搜?

    然后我选择了状压…[听说大爆搜+hash也能做x]

    用一串01串表示这个轮廓 表示从右上开始的一条路径,0表示向左走一步,1表示向下走一步,这样就可以通过一串0和1表示一个轮廓

    每次的操作就是把一个01[左1下1]变成一个10[下1左1]

    然后就是解决博弈的问题,理性分析[感性理解]一下 用dp[st]表示轮廓线状态为st的时候 最小化得分的差值

    然后再感性理解一下

    因为后手在第二步时 有办法选择对自己最优的情况进行转移,所以后手的转移就从他所能到达的状态选择一个最优的状态转移过来,如果当前是先手,就从当前可以到达的状态最劣的状态转移过来[感性理解x]

    因为直接转移的话层次不是很显然,这里采取记忆化搜索实现这个dp[代码细节还是挺多的x]

    Code

    1. #include <bits/stdc++.h>  
    2. using namespace std;  
    3. int N,M;  
    4. bool used[5050006];  
    5. int dp[5050006],qwq;  
    6. int A[25][25],B[25][25];  
    7. int dfs(int st)  
    8. {  
    9.     if (used[st])  
    10.       return dp[st];      
    11.       int x=1,y=N+1,Con=0;  
    12.     int &ans=dp[st];  
    13.     used[st]=1;  
    14.     for (int i=0;i<qwq;i++)  
    15.       if (st&(1<<i)) Con+=y-1;  
    16.       else y--;  
    17.     y=N+1;  
    18.     ans=-1e9;  
    19.     if (st&1) x++;  
    20.     else y--;  
    21.     for (int i=1;i<qwq;i++)  
    22.     {  
    23.       if ((st&(1<<i))&&!(st&(1<<(i-1))))  
    24.          {  
    25.             if (Con%2==0)  
    26.                ans=max(-dfs(st^(1<<i)^(1<<(i-1)))+A[y][x],ans);  
    27.             else ans=max(-dfs(st^(1<<i)^(1<<(i-1)))+B[y][x],ans);  
    28.          }  
    29.       if (st&(1<<i))  
    30.         x++;  
    31.        else y--;  
    32.     }  
    33.     return ans;  
    34. }  
    35. int main()  
    36. {  
    37.     scanf("%d%d",&N,&M);  
    38.     qwq=N+M;      
    39.     used[(1<<M)-1]=1;  
    40.     for (int i=1;i<=N;i++)  
    41.       for (int j=1;j<=M;j++)  
    42.         scanf("%d",&A[i][j]);  
    43.     for (int i=1;i<=N;i++)  
    44.       for (int j=1;j<=M;j++)  
    45.         scanf("%d",&B[i][j]);  
    46.     cout<<dfs(((1<<(N+M))-1)^((1<<N)-1));  
    47.     return 0;  
    48. }  
  • 相关阅读:
    SQL SERVER 2012 第三章 使用INSERT语句添加数据
    SQL SERVER 2012 第三章 T-SQL 基本语句 having子句
    T4 模板生产 多文件
    RAC+DG修改sys密码
    数据泵导入,报错:ORA-12899: value too large for column "SCOTT"."TEST112"."JOIN" (actual: 9, maximum: 8)
    grep过滤空行和注释行
    char与varchar2字符类型的区别
    Oracle不知道用户密码情况下,如何在不更改密码的前提下解锁用户或者延期密码有效期
    数据泵导出报错ORA-31693 ORA-02354 ORA-01466
    安装ogg软件报错:[INS-75012]Sofware Location specified is already an existing Oracle
  • 原文地址:https://www.cnblogs.com/si--nian/p/10478995.html
Copyright © 2011-2022 走看看