zoukankan      html  css  js  c++  java
  • URAL 1519 Formula 1 (插头DP,常规)

    题意:给一个n*m的矩阵,格子中是'*'则是障碍格子,不允许进入,其他格子都是必走的格子,所走格子形成一条哈密顿回路,问有多少种走法?

    思路:

      本来是很基础的题,顿时不知道进入了哪个坑。这篇插头DP的文章够详细,推荐一看(最好不要照抄代码)。

      细节要小心,比如输出用I64d,必须用long long,判断是否无哈密顿回路,位操作等等。

      这次仍然用括号表示法,1表示(,2表示)。

      1 #include <bits/stdc++.h>
      2 #define pii pair<int,int>
      3 #define INF 0x3f3f3f3f
      4 #define LL long long
      5 using namespace std;
      6 const int N=20;
      7 const int mod=12357;
      8 const int NN=1000010;
      9 char g[N][N];
     10 int cur, n, m, ex, ey;
     11 struct Hash_Map
     12 {
     13     int head[mod];      //桶指针
     14     int next[NN];        //记录链的信息
     15     int status[NN];      //状态
     16     LL  value[NN];       //状态对应的DP值。
     17     int size;
     18 
     19     void clear()    //清除哈希表中的状态
     20     {
     21         memset(head, -1, sizeof(head));
     22         size = 0;
     23     }
     24 
     25     void insert(int st, LL val)  //插入状态st的值为val
     26     {
     27         int h = st%mod;
     28         for(int i=head[h]; i!=-1; i=next[i])
     29             if(status[i] == st) //这个状态已经存在,累加进去。
     30             {
     31                 value[i] += val;
     32                 return ;
     33             }
     34         status[size]= st;           //找不到状态st,则插入st。
     35         value[size] = val;
     36         next[size] = head[h] ;      //新插入的元素在队头
     37         head[h] = size++;
     38     }
     39 }hashmap[2];
     40 
     41 int getbit(int s,int pos)   //取出状态s的第pos个插头
     42 {
     43     int bit=0;
     44     if(s&(1<<(2*pos+1)))  bit+=2;    //高位对应高位
     45     if(s&(1<<2*pos))    bit+=1;
     46     return bit;
     47 }
     48 int setbit(int s,int pos,int bit)   //将状态s的第pos个插头设置为bit
     49 {
     50     if(s&(1<<2*pos ))     s^=1<<(2*pos);
     51     if(s&(1<<(2*pos+1)))  s^=1<<(2*pos+1);
     52     return (s|(bit<<2*pos));
     53 }
     54 
     55 int Fr(int s,int pos,int bit)   //寻找状态s的第pos个插头对应的右括号。
     56 {
     57     int cnt=0;
     58     for(pos+=2; pos<m; pos++)
     59     {
     60         if(getbit(s, pos)==3-bit)   cnt++;
     61         if(getbit(s, pos)==bit)     cnt--;
     62         if(cnt==-1)         return setbit(s, pos, 3-bit);
     63     }
     64 }
     65 int Fl(int s,int pos,int bit)   //寻找状态s的第pos个插头对应的左括号。
     66 {
     67     int cnt=0;
     68     for(pos--; pos>=0; pos--)
     69     {
     70         if(getbit(s, pos)==3-bit)  cnt++;
     71         if(getbit(s, pos)==bit)    cnt--;
     72         if( cnt==-1)    return setbit(s, pos, 3-bit);
     73     }
     74 }
     75 
     76 void DP(int i,int j)    //非障碍空格
     77 {
     78     for(int k=0,t; k<hashmap[cur^1].size; k++)
     79     {
     80         int s=hashmap[cur^1].status[k];
     81         LL v=hashmap[cur^1].value[k];
     82         int R=getbit(s,j), D=getbit(s,j+1);
     83         if(g[i][j]=='*')    //障碍格子
     84         {
     85             if( R==0 && D==0 )    hashmap[cur].insert(s, v);
     86             continue ;
     87         }
     88         if(R && D)  //两个括号
     89         {
     90             t=(setbit(s,j,0)&setbit(s,j+1,0));
     91             if(R==D)    //同个方向的括号
     92             {
     93                 if(R==1)    t=Fr(t, j, 2);  //要改
     94                 else        t=Fl(t, j, 1);
     95                 hashmap[cur].insert(t, v);
     96             }
     97             if( R==2 && D==1 )        //不同的连通分量
     98                 hashmap[cur].insert(t, v);
     99             if(i==ex && j==ey && R==1 && D==2 )  //终点时'('和')'才可以合并。
    100                 hashmap[cur].insert(t, v);
    101         }
    102         else if(R || D)     //仅1个括号
    103         {
    104             hashmap[cur].insert(s,v);
    105             if(R)   t=setbit(setbit(s,j,0),j+1,R);
    106             else    t=setbit(setbit(s,j+1,0),j,D);
    107             hashmap[cur].insert(t,v);
    108         }
    109         else                //无括号
    110             hashmap[cur].insert( setbit(s,j,1)|setbit(s,j+1,2), v);
    111     }
    112 }
    113 
    114 void cal()
    115 {
    116     if(ex==-1)  return ;  //无空格
    117     for(int i=0; i<n; i++)
    118     {
    119         cur^=1;
    120         hashmap[cur].clear();
    121         for(int j=0; j<hashmap[cur^1].size; j++)    //新行,需要左移一下状态。
    122             if( getbit( hashmap[cur^1].status[j], m)==0 )   //多余的状态需要去除
    123                 hashmap[cur].insert( hashmap[cur^1].status[j]<<2, hashmap[cur^1].value[j] );
    124         for(int j=0; j<m; j++)
    125         {
    126             cur^=1;
    127             hashmap[cur].clear();
    128             DP(i,j);
    129             if(i==ex && j==ey)    return ;  //终点
    130         }
    131     }
    132 }
    133 
    134 LL print()
    135 {
    136     for(int i=0; i<hashmap[cur].size; i++)  //寻找轮廓线状态为0的值。
    137         if(  hashmap[cur].status[i]==0 )
    138             return hashmap[cur].value[i];
    139     return 0;
    140 }
    141 int main()
    142 {
    143     //freopen("input.txt", "r", stdin);
    144     while(~scanf("%d%d",&n,&m))
    145     {
    146         ex=ey=-1;
    147         cur=0;
    148         for(int i=0; i<n; i++)      //输入矩阵
    149             for(int j=0; j<m; j++)
    150             {
    151                 char c=getchar();
    152                 if(c=='.'||c=='*')
    153                 {
    154                     g[i][j]=c;
    155                     if( c=='.' )    ex=i,ey=j;//终点空格
    156                 }
    157                 else    j--;
    158             }
    159 
    160         hashmap[cur].clear();
    161         hashmap[cur].insert(0, 1);  //初始状态
    162         cal();
    163         cout<<print()<<endl;
    164     }
    165     return 0;
    166 }
    AC代码
  • 相关阅读:
    WPF中图形表示语法详解(Path之Data属性语法)ZZ
    C#/.NET Little Wonders: Use Cast() and OfType() to Change Sequence Type(zz)
    WPF在DLL中读取Resource的方法
    CENTOS6.5安装CDH5.12.1(一) https://mp.weixin.qq.com/s/AP_m0QqKgzEUfjf0PQCX-w
    Buildroot stress-ng Linux系统压力测试
    Jenkins+git
    MySql5.7配置文件my.cnf设置
    mongoDB 删除集合后,空间不释放
    有赞MySQL自动化运维之路—ZanDB
    TIDB介绍 新数据库趋势
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4788453.html
Copyright © 2011-2022 走看看