zoukankan      html  css  js  c++  java
  • POJ 3254 Corn Fields (状压DP,轮廓线DP)

    题意:

      有一个n*m的矩阵(0<n,m<=12),有部分的格子可种草,有部分不可种,问有多少种不同的种草方案(完全不种也可以算1种,对答案取模后输出)?

    思路:

      明显的状压DP啦,只是怎样压缩状态?跟轮廓线DP一样,按格子为单位来设计状态,一个状态只需要表示到其上方和左方的格子,所以最多只需要保存min(n,m)个01状态就行了(可以尝试旋转一下矩阵),最多需要12位。用哈希表来做会比较快吧,不用去考虑无效的状态,比如出现相邻两个1。

      1 //#include <bits/stdc++.h>
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <map>
      7 #include <algorithm>
      8 #include <vector>
      9 #include <iostream>
     10 #define pii pair<int,int>
     11 #define INF 0x7f3f3f3f
     12 #define LL long long
     13 #define ULL unsigned long long
     14 using namespace std;
     15 const double PI  = acos(-1.0);
     16 const int N=13;
     17 const int M=100000000;
     18 int g[N][N];
     19 struct Hash_Map
     20 {
     21     static const int mod=1237;
     22     static const int N=10000;
     23     int head[mod];      //桶指针
     24     int next[N];        //记录链的信息
     25     int status[N];      //状态
     26     int  value[N];       //状态对应的DP值。
     27     int size;
     28     void clear()    //清除哈希表中的状态
     29     {
     30         memset(head, -1, sizeof(head));
     31         size = 0;
     32     }
     33 
     34     void insert(int st, int val)  //插入状态st的值为val
     35     {
     36         int h = st%mod;
     37         for(int i=head[h]; i!=-1; i=next[i])
     38         {
     39             if(status[i] == st) //这个状态已经存在,累加进去。
     40             {
     41                 value[i] += val;
     42                 value[i]%=M;
     43                 return ;
     44             }
     45         }
     46         status[size]= st;           //找不到状态st,则插入st。
     47         value[size] = val;
     48         next[size] = head[h] ;      //新插入的元素在队头
     49         head[h] = size++;
     50     }
     51 }hashmap[2];
     52 
     53 int cal(int n,int m)
     54 {
     55     int cur=0, mod=(1<<m-1)-1;
     56     hashmap[cur].clear();
     57     hashmap[0].insert(0,1);
     58     for(int i=1; i<=n; i++)
     59     {
     60         for(int j=1; j<=m; j++)
     61         {
     62             cur^=1;
     63             hashmap[cur].clear();
     64             for(int k=0; k<hashmap[cur^1].size; k++)
     65             {
     66                 int s=hashmap[cur^1].status[k];
     67                 int v=hashmap[cur^1].value[k];
     68                 int t=(s&mod)<<1;   //去掉最高位
     69                 hashmap[cur].insert(t,v);       //不放
     70                 if(g[i][j])
     71                 {
     72                     if( s&(1<<m-1) )    continue;
     73                     if( j!=1 && (s&1) ) continue;   //不能放
     74                     hashmap[cur].insert(t^1,v);
     75                 }
     76             }
     77         }
     78     }
     79     int ans=0;
     80     for(int k=0; k<hashmap[cur].size; k++)
     81     {
     82         ans+=hashmap[cur].value[k];
     83         ans%=M;
     84     }
     85     return ans;
     86 }
     87 
     88 
     89 int main()
     90 {
     91     //freopen("input.txt","r",stdin);
     92     int n, m;
     93     while(~scanf("%d%d",&n,&m))
     94     {
     95         for(int i=1; i<=n; i++)
     96             for(int j=1; j<=m; j++)
     97                 scanf("%d",&g[i][j]);
     98         printf("%d
    ",cal(n,m));
     99     }
    100     return 0;
    101 }
    AC代码
  • 相关阅读:
    SQL SERVER 如何处理带字母的自增列--【叶子】
    实现对数据进行分组小计并计算合计的实例 asp.net
    sql 随笔
    事务
    游标
    触发器
    Session的生命周期
    ASP.NET 推荐书籍
    asp.net 查询本地excel 获取信息
    使用DotNetZip压缩与解压缩
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4857690.html
Copyright © 2011-2022 走看看