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代码
  • 相关阅读:
    pandas Dataframe filter
    process xlsx with pandas
    data manipulate in excel with easyExcel class
    modify registry in user environment
    add number line in vim
    java import webservice
    ctypes MessageBoxA
    music 163 lyrics
    【python实例】自动贩卖机
    【python基础】sys模块(库)方法汇总
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4788453.html
Copyright © 2011-2022 走看看