zoukankan      html  css  js  c++  java
  • 【插头DP】BZOJ1187- [HNOI2007]神奇游乐园

    【题目大意】

    在n*m的网格中选一条回路,使权值和最大。

    【思路】

    和之前裸的插头DP差不多,只不过现在回路不需要经过所有的格子。所以有以下几个注意点(具体看注释):

    (1)left和up插头相等的时候,直接更新答案;

    (2)left和up插头不存在的时候,还要考虑当前格子不取的情况。

    orz写了半天,感觉被掏空.jpg

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int MAXN=10;
      5 const int MAXM=105;
      6 const int HASH=30007;
      7 const int INF=0x7fffffff;
      8 ll ans=-1ll << 60;
      9 int n,m,sat[MAXM][MAXN];
     10 int code[MAXN];
     11 
     12 struct HashMap
     13 {
     14     vector<int> hash[HASH];
     15     vector<ll> state,f;
     16     
     17     void clear()
     18     {
     19         for(int i=0;i<HASH;i++) vector<int>().swap(hash[i]);
     20         vector<ll>().swap(state);
     21         vector<ll>().swap(f);
     22     }
     23     
     24     void push(ll st,ll ans)
     25     {
     26         int h=st%HASH;
     27         for (int i=0;i<hash[h].size();i++)
     28         {
     29             int now=hash[h][i];
     30             if (state[now]==st)
     31             {
     32                 f[now]=max(f[now],ans);
     33                 return;
     34             }
     35         }
     36         state.push_back(st);
     37         f.push_back(ans);
     38         hash[h].push_back(state.size()-1);
     39     }
     40 }dp[2];
     41 
     42 void decode(ll state)
     43 {
     44     memset(code,0,sizeof(code));
     45     for (int i=n;i>=0;i--)
     46     {
     47         code[i]=state&7;
     48         state>>=3;
     49     }
     50 }
     51 
     52 void shift()
     53 {
     54     for (int i=n;i>0;i--) code[i]=code[i-1];
     55     code[0]=0;
     56 } 
     57 
     58 ll encode()
     59 {
     60     int ch[MAXN],cnt=0;
     61     memset(ch,-1,sizeof(ch));
     62     ch[0]=0;
     63     ll ret=0;
     64     for (int i=0;i<=n;i++)
     65     {
     66         if (ch[code[i]]==-1) ch[code[i]]=++cnt;
     67         code[i]=ch[code[i]];
     68         ret<<=3;
     69         ret|=code[i];
     70     }
     71     return ret;
     72 }
     73 
     74 void dpblank(int i,int j,int cur)
     75 {
     76     for (int k=0;k<dp[1-cur].state.size();k++)
     77     {
     78         decode(dp[1-cur].state[k]);
     79         if (j==1)//把之前shift的写法改成这样写了,总之就过了,也不知道为什么orz 
     80         {
     81             if (code[n]) continue;
     82             shift();
     83         }
     84         int left=code[j-1],up=code[j];
     85         
     86         if (left && up)
     87         {
     88             code[j-1]=code[j]=0;
     89             if (left==up)
     90             {
     91                 if (encode()==0) ans=max(ans,dp[1-cur].f[k]+sat[i][j]);
     92                 //注意和之前不一样的地方:如果已经封闭起来了就更新答案 
     93             }
     94             else
     95             {
     96                 for (int t=0;t<=n;t++) if (code[t]==left) code[t]=up;
     97                 dp[cur].push(encode(),dp[1-cur].f[k]+sat[i][j]);
     98             }
     99         }
    100         
    101         if ((left && (!up)) || (up && (!left)))
    102         {
    103             int t=left|up;
    104             code[j-1]=0;
    105             code[j]=t;
    106             dp[cur].push(encode(),dp[1-cur].f[k]+sat[i][j]);             
    107             code[j-1]=t;
    108             code[j]=0;
    109             dp[cur].push(encode(),dp[1-cur].f[k]+sat[i][j]);
    110         }
    111         
    112         if (!left && !up)
    113         { 
    114             dp[cur].push(encode(),dp[1-cur].f[k]);
    115             //注意并不一定是所有格子都要经过,所以还要考虑不经过当前格子的情况 
    116             code[j-1]=code[j]=MAXN-1;
    117             dp[cur].push(encode(),dp[1-cur].f[k]+sat[i][j]);
    118         }
    119     }
    120 }
    121 
    122 void init()
    123 {
    124     scanf("%d%d",&m,&n);
    125     for (int i=1;i<=m;i++)
    126         for (int j=1;j<=n;j++) scanf("%d",&sat[i][j]);
    127 }
    128 
    129 void solve()
    130 {
    131     int cur=0;
    132     dp[cur].clear();
    133     dp[cur].push(0,0);
    134     for (int i=1;i<=m;i++)
    135         for (int j=1;j<=n;j++)
    136         {
    137             cur^=1;
    138             dp[cur].clear();
    139             dpblank(i,j,cur);
    140         }
    141     printf("%lld",ans);
    142 }
    143 
    144 int main()
    145 {
    146     init();
    147     solve();
    148     return 0;
    149 }
  • 相关阅读:
    java中volatile关键字的含义
    2019年个人总结
    跟随Javac代码来解答字节码的疑惑
    Python装饰器实现带参数和不带参数
    try with resource当中你没有注意到点。。
    IDEA中,已经被加到版本库的文件如何在提交的时候忽略它们
    连接mysql客户端报错: java.sql.SQLException: Unable to load authentication plugin 'caching_sha2_password'
    从字节码层次看i++和++i
    对lambda表达式的字节码实现个人理解
    解决mvn clean install的报错The packaging for this project did not assign a file to the build artifact
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5925784.html
Copyright © 2011-2022 走看看