zoukankan      html  css  js  c++  java
  • URAL 1519 基础插头DP

     题目大意:

    给定一个图,一部分点'*'作为障碍物,求经过所有非障碍点的汉密尔顿回路有多少条

    基础的插头DP题目,对于陈丹琦的论文来说我觉得http://blog.sina.com.cn/s/blog_51cea4040100gmky.html

    这个博客写的更容易理解,不过好像这篇博客里的代码有问题,反正是A不了题目的

    不过上面的图和思路写的很清楚,可以作为参考

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    #define ll unsigned long long
    const int HASH_SIZE = 199917;
    
    bool mp[15][15];
    char str[15][15];
    int n, m , k , nn , mm;
    int tot[2] , bit[15] , hash[HASH_SIZE] , state[2][HASH_SIZE];
    ll dp[2][HASH_SIZE] , ans;
    
    void init()
    {
        //每一位用4进制保存,那么对于每一个状态来说都是右移2次,所以这里i*2
        for(int i=0 ; i<=13 ; i++) bit[i] = i<<1;
        memset(dp , 0 , sizeof(dp));
        tot[0] = dp[0][1] = 1 , ans = k = 0;
        state[0][1] = 0;
    }
    
    void hash_in(int s , ll sum)//s表示当前状态,sum是指s状态下共有sum种方式形成
    {
       // print(s);
       // cout<<" "<<sum<<endl;
        int p = s%HASH_SIZE;
        while(hash[p]){
            if(state[k][hash[p]] == s){
                dp[k][hash[p]] += sum;
                return ;
            }
            p++;
            if(p == HASH_SIZE) p=0;
        }
        hash[p] = ++tot[k];
        state[k][hash[p]] = s;
        dp[k][hash[p]] = sum;
    }
    
    void work()
    {
        for(int i=1 ; i<=n ; i++){
            for(int j=1 ; j<=m ; j++){
                k^=1 ; //滚动数组
                tot[k] = 0;
                memset(hash , 0 , sizeof(hash));
                for(int u=1 ; u<=tot[1-k] ; u++){
                    int s = state[1-k][u] , curs;
                    ll sum = dp[1-k][u];
                    int p = (s>>bit[j-1])&3 , q = (s>>bit[j])&3; //3进制 , 用( , # , )来理解
                    if(!mp[i][j]){
                        if(p==0 && q==0) hash_in(s , sum);
                    }
                    else{
                        if(p == 0 && q == 0){
                            if(!mp[i+1][j] || !mp[i][j+1]) continue;
                            curs = s + (1<<bit[j-1]) + (2<<bit[j]);
                            hash_in(curs , sum);
                        }
                        else if(!p && q){
                            if(mp[i][j+1]) hash_in(s , sum);
                            if(mp[i+1][j]){
                                curs = s+q*(1<<bit[j-1])-q*(1<<bit[j]);
                                hash_in(curs , sum);
                            }
                        }
                        else if(p && !q){
                            if(mp[i+1][j]) hash_in(s , sum);
                            if(mp[i][j+1]){
                                curs = s - p*(1<<bit[j-1])+p*(1<<bit[j]);
                                hash_in(curs , sum);
                            }
                        }
                        else if(p+q==2){ //可理解为p==1 && q==1
                            int cnt = 1;
                            for(int v=j+1 ; v<=m ; v++){
                                int w = (s>>bit[v])&3;
                                if(w == 1) cnt++;
                                if(w == 2) cnt--;
                                if(!cnt){
                                    curs = s-(1<<bit[v]); //将)转化为( ->状态由2->1 , 减少了一个
                                    break;
                                }
                            }
                            curs = curs-(1<<bit[j])-(1<<bit[j-1]);
                            hash_in(curs , sum);
                        }
                        else if(p+q==4){//可理解为p==2 && q==2
                            int cnt = 1;
                            for(int v=j-2 ; v>=1 ; v--){
                                int w = (s>>bit[v])&3;
                                if(w == 1) cnt--;
                                if(w == 2) cnt++;
                                if(!cnt){
                                    curs= s+(1<<bit[v]);
                                    break;
                                }
                            }
                            curs = curs-(2<<bit[j])-(2<<bit[j-1]);
                            hash_in(curs , sum);
                        }
                        else if(p==1 && q==2){
                            if(i==nn && j==mm)
                                ans+=sum;
                        }
                        else if(p==2 && q==1){
                            curs = s-(2<<bit[j-1])-(1<<bit[j]);
                            hash_in(curs , sum);
                        }
                    }
                }
            }
            for(int j=1 ; j<=tot[k] ; j++) state[k][j]<<=2;
        }
        printf("%lld
    " , ans);
    }
    
    int main()
    {
       // freopen("in.txt" , "r" , stdin);
        while(~scanf("%d%d" , &n , &m))
        {
            memset(mp , 0 , sizeof(mp));
            for(int i=1 ; i<=n ; i++){
                scanf("%s" , str[i]+1);
                for(int j=1 ; j<=m ; j++){
                    mp[i][j] = str[i][j]=='.';
                   // if(mp[i][j]) cout<<i<<" "<<j<<endl;
                    if(mp[i][j]) nn=i , mm=j;//记录最后一个可执行块
                }
            }
            init();
            work();
        }
        return 0;
    }
    View Code

    后来写hdu上的题目的时候觉得kuangbin的表达方式还是很清晰的,所以又将源代码修改成了:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <iostream>
      5 
      6 using namespace std;
      7 #define ll unsigned long long
      8 const int HASH = 10007;
      9 const int STATE = 1000010;
     10 const int MAXD = 15;
     11 int  n , m , enx , eny;
     12 int code[MAXD] , mp[MAXD][MAXD];
     13 ll ans = 0;
     14 
     15 struct HASHMAP{
     16     int head[HASH] , next[STATE] , state[STATE] , size;
     17     ll f[STATE];
     18 
     19     void init(){
     20         size = 0;
     21         memset(head , -1 , sizeof(head));
     22     }
     23 
     24     void push_in(int st , ll sum){
     25         int h = st%HASH;
     26         for(int i = head[h] ; ~i ; i=next[i]){
     27             if(st == state[i]){
     28                 f[i]+=sum;
     29                 return ;
     30             }
     31         }
     32         f[size]=sum;
     33         state[size] = st;
     34         next[size] = head[h];
     35         head[h] = size++;
     36     }
     37 }hashmap[2];
     38 
     39 void decode(int *code , int m , int st)
     40 {
     41     for(int i=m ; i>=0 ; i--){
     42         code[i] = st&3;
     43         st>>=2;
     44     }
     45 }
     46 
     47 int encode(int *code , int m)
     48 {
     49     int st=0;
     50     for(int i=0 ; i<=m ; i++){
     51         st<<=2;
     52         st |= code[i];
     53     }
     54     return st;
     55 }
     56 
     57 void init()
     58 {
     59     char str[MAXD][MAXD];
     60     for(int i=1 ; i<=n ; i++){
     61         scanf("%s" , str[i]+1);
     62         for(int j=1 ; j<=m ; j++){
     63             if(str[i][j] == '.'){
     64                 mp[i][j] = 1;
     65                 enx = i , eny = j;
     66             }else mp[i][j] = 0;
     67         }
     68         mp[i][m+1]=0;
     69         mp[n+1][i] = 0;
     70     }
     71 }
     72 
     73 void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧
     74 {
     75     for(int i=m ; i>=0 ; i--) code[i] = code[i-1];
     76     code[0] = 0;
     77 }
     78 
     79 void dpblank(int i , int j , int cur) //处理可执行格子
     80 {
     81    // cout<<"ok: "<<i<<" "<<j<<endl;
     82     int k , left , up;
     83     for(k=0 ; k<hashmap[cur].size ; k++){
     84         decode(code , m , hashmap[cur].state[k]);
     85         left = code[j-1];
     86         up = code[j];
     87         if(!left && !up){
     88             if(!mp[i][j+1] || !mp[i+1][j]) continue;
     89             code[j-1] = 1 , code[j] = 2;
     90             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
     91         }
     92         else if(!left && up){
     93             if(mp[i][j+1]) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
     94             if(mp[i+1][j]){
     95                 code[j-1] = up , code[j] = 0;
     96                 if(j == m) shift(code , m);
     97                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
     98             }
     99         }
    100         else if(left && !up){
    101             if(mp[i+1][j]){
    102                 if(j == m)  shift(code , m);
    103                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
    104             }
    105             if(mp[i][j+1]){
    106                 code[j-1] = 0 , code[j] = left;
    107                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
    108             }
    109         }
    110         else if(left==1 && up == 1){
    111             int cnt = 1;
    112             for(int v=j+1 ; v<=m ; v++){
    113                 if(code[v]==1)cnt++;
    114                 if(code[v]==2)cnt--;
    115                 if(!cnt){
    116                     code[v]=1;
    117                     break;
    118                 }
    119             }
    120             code[j-1] = code[j] = 0;
    121             if(j == m) shift(code , m);
    122             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
    123         }
    124         else if(left == 2 && up == 2){
    125             int cnt=1;
    126             for(int v=j-2 ; v>=1 ; v--){
    127                 if(code[v]==2)cnt++;
    128                 if(code[v]==1)cnt--;
    129                 if(!cnt){
    130                     code[v]=2;
    131                     break;
    132                 }
    133             }
    134             code[j-1] = code[j] = 0;
    135             if(j == m) shift(code , m);
    136             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
    137         }
    138         else if(left==1 && up==2){
    139             if(i==enx && j==eny) ans+=hashmap[cur].f[k];
    140         }
    141         else{
    142             code[j-1]=code[j]=0;
    143             if(j == m) shift(code , m);
    144             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
    145         }
    146     }
    147 }
    148 
    149 void dpblock(int i , int j , int cur)
    150 {
    151    // cout<<"flase: "<<i<<" "<<j<<endl;
    152     int k , left , up;
    153     for(k=0 ; k<hashmap[cur].size ; k++){
    154         decode(code , m , hashmap[cur].state[k]);
    155         left = code[j-1] , up = code[j];
    156         if(!left && !up){
    157             if(j == m) shift(code , m);
    158             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
    159         }
    160     }
    161 }
    162 
    163 ll solve()
    164 {
    165     ans = 0;
    166     int cur = 0;
    167     hashmap[cur].init();
    168     hashmap[cur].push_in(0 , 1);
    169     for(int i=1 ; i<=n ; i++){
    170         for(int j=1 ; j<=m ; j++){
    171             hashmap[cur^1].init();
    172             if(mp[i][j]) dpblank(i , j , cur);
    173             else dpblock(i , j , cur);
    174             cur ^= 1;
    175         }
    176     }
    177     return ans;
    178 }
    179 
    180 int main()
    181 {
    182   //  freopen("in.txt" , "r" , stdin);
    183     while(~scanf("%d%d" , &n , &m))
    184     {
    185         init();
    186         printf("%I64d
    " , solve());
    187     }
    188     return 0;
    189 }
    View Code
  • 相关阅读:
    [Lydsy1805月赛]口算训练 BZOJ5358
    我所不知的JS
    基于Spring Cloud 几行配置完成单点登录开发
    彻底终结MySQL同步延迟问题
    编写优秀 CSS 代码的 8 个策略
    10个用Java谋生非常有趣的方式
    深入理解JVM-垃圾回收器
    SpringBoot下文件上传与下载的实现
    java 使用面向对象方式实现录入学生信息,取出成绩最大值、最小值、平均值、对其进行排序
    JavaSE基础:泛型
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4718288.html
Copyright © 2011-2022 走看看