zoukankan      html  css  js  c++  java
  • 玉米田【状压DP】【记搜】

    题目大意:

    一个n×m的矩阵里,有几个是可以种植玉米的。求玉米种植不相连的方案数。


    思路:

    DFS爆搜 能拿90分,正解是状压DP。
    可以把可种植玉米的土地用1表示,贫瘠的土地用0表示,每一行串成的数字就是一个二进制数,状态压缩后,就成了一个较小的十进制数。
    f[i][j]表示在第i行,状态压缩后的十进制数为j的情况下,总共种植的方案数。那么,若k&j=j,那么说明在上一行的种植情况为k时,这一行种植情况为j是合法的(即没有两个玉米种植位置相连)。那么f[i][j]就与f[i1][k]可以成立,f[i][j]+=f[i1][k]
    最终答案就是i=02m1f[n][i]


    代码:

    #include <cstdio>
    #include <iostream>
    #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
    using namespace std;
    
    int n,m,a[21][21],g[21],f[21][5001],ms,num[41],sum;
    bool state[5001];
    
    int main()
    {
        fre(cowfood);
        scanf("%d%d",&n,&m);
        num[1]=1;
        for (int i=2;i<=30;i++)
         num[i]=num[i-1]*2;  //为下面求2^i初始化
        for (int i=1;i<=n;i++)
         for (int j=1;j<=m;j++)
         {
            scanf("%d",&a[i][j]);
            g[i]=g[i]+num[j]*a[i][j];  //状态压缩
         }
        ms=num[m+1];  //2^m
        for (int i=0;i<ms;i++)
         state[i]=((!((i<<1)&i))&&(!((i>>1)&i)));  //初始化
        f[0][0]=1;
        for (int i=1;i<=n;i++)
         for (int j=0;j<ms;j++)
          if (state[j]&&((j&g[i])==j))  //为j的情况合法
           for (int k=0;k<ms;k++)
            if (!(j&k))  //k在上一行的情况合法
             f[i][j]+=f[i-1][k];
        for (int j=0;j<ms;j++)
         sum=(sum+f[n][j])%100000000;
        return printf("%d\n",sum)&0;
    }
  • 相关阅读:
    汇编学习笔记
    英语口语学习
    三层架构与MVC的区别
    “Razor” – a new view engine for ASP.NET
    代码生成
    最热门的敏捷书籍[转]
    推荐工具
    在IBM发现管理的真相[转]
    开源的通用帮助库
    单元测试
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998858.html
Copyright © 2011-2022 走看看