• [USACO06NOV]玉米田Corn Fields 状压DP


    题面:

    农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地。John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

    遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。

    John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

    输出一个整数,即牧场分配总方案数除以100,000,000的余数。

    题解:

    emmm。。。一道不难的状压DP

    设f[i][j]表示到i行,状态为j的方案数,

    因为相邻两块土地不能选,所以我们可以先dfs搜出所有可能状态,

    这样状态数暴跌10倍,,,貌似很划得来的样子,不过不这样好像也可以,但是DP判断的地方也会麻烦一些。。。

    然后存下不能放的地方,并标记为1,(同样用状压)

    依次枚举行,当前状态,上一行状态,统计并取模即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 15
     5 #define LL long long
     6 #define mod 100000000
     7 int n,m,tmp,ans,tot;
     8 int f[AC][400],s[AC],num[400];//error!!!状态要开400,,,
     9 
    10 
    11 void pre()
    12 {
    13     int a;
    14     scanf("%d%d",&n,&m);
    15     for(R i=1;i<=n;i++)
    16         for(R j=1;j<=m;j++)
    17         {
    18             scanf("%d",&a);
    19             if(!a)    s[i] |= 1 << (m - j);//给定状态也要压 
    20         }
    21 }
    22 
    23 void dfs(int x,int now)
    24 {
    25     if(x)    tmp+=1 << (m - now);
    26     if(now == m)
    27     {
    28         num[++tot]=tmp;
    29         if(x) tmp-=1 << (m - now);
    30         return ;
    31     }
    32     if(x) dfs(0,now+1);
    33     else 
    34     {
    35         dfs(0,now+1);
    36         dfs(1,now+1);
    37     }
    38     if(x)     tmp-=1 << (m - now);
    39 }
    40 
    41 void work()
    42 {
    43     for(R i=1;i<=tot;i++)//第一行特殊处理
    44     {
    45         if(s[1] & num[i]) continue;
    46         f[1][i]=1;
    47     }
    48     for(R i=2;i<=n;i++)//枚举行
    49     {
    50         for(R j=1;j<=tot;j++)//枚举当前行状态
    51         {
    52             if(s[i] & num[j]) continue;
    53             for(R k=1;k<=tot;k++)//枚举上一行状态
    54             {
    55                 if(s[i-1] & num[k]) continue;
    56                 if(num[j] & num[k]) continue;
    57                 f[i][j] += f[i-1][k];
    58                 f[i][j] %= mod;
    59                 //if(f[i][j] > mod) f[i][j] -= mod;
    60             }
    61         }
    62     }
    63     for(R i=1;i<=tot;i++) 
    64     {
    65         ans+=f[n][i];
    66         ans%=mod;
    67         //if(ans > mod) ans-=mod;
    68     }
    69     printf("%d
    ",ans);
    70 }
    71 
    72 int main()
    73 {
    74 //    freopen("in.in","r",stdin);
    75     pre();
    76     dfs(1,1);//获取所有有效状态
    77     dfs(0,1);
    78     work();
    79     //fclose(stdin);
    80     return 0;
    81 }
  • 相关阅读:
    推荐一款快得令地发指本地搜索软件:Everything,绝对改变对NTFS的看法
    “/”应用程序中的服务器错误 WebParts开发时出现的错误
    《让人无法说 NO的攻心说话术》摘要
    UXWEEK
    2012中国交互设计体验日演讲实录
    彩色铅笔入门
    ClickOnce证书签名
    DevExpress控件使用小结
    解决ClickOnce签名过期问题
    属于自己的小小空间
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9097805.html
Copyright © 2020-2023  润新知