zoukankan      html  css  js  c++  java
  • HDU 1693 二进制表示的简单插头dp

     题目大意:

    找到多条回路覆盖所有非障碍格子,问这样回路的种数

    这里的插头与URAL1519 不一样的是 只要管它是否存在即可,只需要1个二进制位表示状态

      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 ;
     12 int code[MAXD] , mp[MAXD][MAXD];
     13 
     14 struct HASHMAP{
     15     int head[HASH] , next[STATE] , state[STATE] , size;
     16     ll f[STATE];
     17 
     18     void init(){
     19         size = 0;
     20         memset(head , -1 , sizeof(head));
     21     }
     22 
     23     void push_in(int st , ll sum){
     24         int h = st%HASH;
     25         for(int i = head[h] ; ~i ; i=next[i]){
     26             if(st == state[i]){
     27                 f[i]+=sum;
     28                 return ;
     29             }
     30         }
     31         f[size]=sum;
     32         state[size] = st;
     33         next[size] = head[h];
     34         head[h] = size++;
     35     }
     36 }hashmap[2];
     37 
     38 void decode(int *code , int m , int st)
     39 {
     40     for(int i=m ; i>=0 ; i--){
     41         code[i] = st&1;
     42         st>>=1;
     43     }
     44 }
     45 
     46 int encode(int *code , int m)
     47 {
     48     int st=0;
     49     for(int i=0 ; i<=m ; i++){
     50         st<<=1;
     51         st |= code[i];
     52     }
     53     return st;
     54 }
     55 
     56 void init()
     57 {
     58     scanf("%d%d" , &n , &m);
     59     for(int i=1 ; i<=n ; i++){
     60         for(int j=1 ; j<=m ; j++){
     61             scanf("%d" , &mp[i][j]);
     62         }
     63     }
     64 }
     65 
     66 void shift(int *code , int m) //换行,可理解为将最右侧轮廓线换到了下一行的最左侧
     67 {
     68     for(int i=m ; i>=0 ; i--) code[i] = code[i-1];
     69     code[0] = 0;
     70 }
     71 
     72 void dpblank(int i , int j , int cur) //处理可执行格子
     73 {
     74    // cout<<"ok: "<<i<<" "<<j<<endl;
     75     int k , left , up;
     76     for(k=0 ; k<hashmap[cur].size ; k++){
     77         decode(code , m , hashmap[cur].state[k]);
     78         left = code[j-1];
     79         up = code[j];
     80         if(left&&up){ //插头均存在 1 1
     81             code[j-1] = code[j] = 0;
     82             if(j == m) shift(code , m);
     83             hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
     84           //  cout<<i<<" "<<j<<" "<<encode(code , m)<<" "<<hashmap[cur].f[k]<<endl;
     85         }
     86         else if(left || up){ // 1 || 1
     87             if(j<m && mp[i][j+1]){
     88                 //这里面右插头是可选的,所以不存在换行shift()
     89                 code[j-1] = 0 , code[j] = 1;
     90                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
     91             }
     92             if(i<n && mp[i+1][j]){
     93                 code[j-1] = 1 , code[j] = 0;
     94                 if(j == m) shift(code , m);
     95                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
     96             }
     97         }
     98         else {
     99             if((j<m && mp[i][j+1]) && (i<n && mp[i+1][j])){
    100                 code[j-1] = code[j] = 1;
    101                 hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
    102             }
    103         }
    104     }
    105 }
    106 
    107 void dpblock(int i , int j , int cur)
    108 {
    109    // cout<<"flase: "<<i<<" "<<j<<endl;
    110     int k , left , up;
    111     for(k=0 ; k<hashmap[cur].size ; k++){
    112         decode(code , m , hashmap[cur].state[k]);
    113         left = code[j-1] , up = code[j];
    114         if(j == m) shift(code , m);
    115         if(left+up == 0) hashmap[cur^1].push_in(encode(code , m) , hashmap[cur].f[k]);
    116     }
    117 }
    118 
    119 ll solve()
    120 {
    121     ll ans = 0;
    122     int cur = 0;
    123     hashmap[cur].init();
    124     hashmap[cur].push_in(0 , 1);
    125     for(int i=1 ; i<=n ; i++){
    126         for(int j=1 ; j<=m ; j++){
    127             hashmap[cur^1].init();
    128             if(mp[i][j]) dpblank(i , j , cur);
    129             else dpblock(i , j , cur);
    130             cur ^= 1;
    131         }
    132     }
    133     for(int i=0 ; i<hashmap[cur].size ; i++)
    134         ans += hashmap[cur].f[i];
    135     return ans;
    136 }
    137 
    138 int main()
    139 {
    140    // freopen("in.txt" , "r" , stdin);
    141     int T , cas=0;
    142     scanf("%d" , &T);
    143     while(T--)
    144     {
    145         init();
    146         printf("Case %d: There are %I64u ways to eat the trees.
    " , ++cas , solve());
    147     }
    148     return 0;
    149 }
  • 相关阅读:
    Python 文件批量改名
    解决 unity 生成 android apk read Resources
    IIS 重定向 自动追加 eurl.axd 后缀
    多线程
    zookeeper面试
    线程之间的通信(thread signal)
    软考高项之计算题成本类计算
    PowerDesigner PDM 复制comment到name
    软考高项之计算题进度类
    全面理解Java内存模型
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4725363.html
Copyright © 2011-2022 走看看