• Luogu-P1879 [USACO06NOV]玉米田Corn Fields


    题目

    题目链接

    测试得分:  100

    主要算法 :  状压DP(二进制优化)

    题干:

       状压DP板子

    分析

      1.就是像之前的互不侵犯一样,只是合法状态还要判断要与玉米地的贫瘠程度,是否可以种植玉米有关

      2.向互不侵犯一样,判读是否两两相邻

      3.好了上代码了

      代码

    #include<stdio.h>
    #include<stdlib.h>
    #define FORa(i,s,e) for(int i=s;i<=e;i++)
    #define FORs(i,s,e) for(int i=s;i>=e;i--)
    #define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++
    #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout);
    
    using namespace std;
    char buf[100000],*pa,*pb;
    inline int read();
    
    const int SUM=4096,N=12,MOD=100000000;
    int n,m,ans,f[N+1][SUM+1];
    /*f[i][j]代表的是前i行且第i行的状态为j满足的方案数 
    j原本是一维的有n个元素的数组,代表的是第i行的状态,但是对于状态只有01两种选择,放与不放
    所以可以将01串看作二进制数,则每一个状态对应一个唯一的十进制数,这就是这一题的核心思想状压 
    还有就是要符合这片土地是否可以种植 
    */
    struct Node{
        int num,s[SUM+1];
    }a[N+1];
    void Pretreatment(int i,int t)
    {
        for(int j=0,jn=(1<<m);j<jn;j++)//枚举每一行的状态 
        {
            if((j&(j<<1))||(j&(j>>1))||(j&t)) continue;
            /*如果有左右两个相邻都种植corn的话就不合法
            还有就是要符合这片土地是否可以种植 
            原本是为0的不能种植,但因为位运算的一些操作是对于1敏感
            所以此处有一种特殊的解决方法,就是将土地初始状态反向转化,0变成1,1变成0
            所以与现在枚举的状态如果有交集,直接忽略*/ 
            a[i].s[++a[i].num]=j;//累加每一行的状态 
        }
    }
    void Dp()
    {
        FORa(i,1,a[1].num) f[1][i]=1;
        FORa(i,2,n)
            FORa(j,1,a[i].num)//枚举这一行所有合法状态
                FORa(k,1,a[i-1].num)//枚举下一行所有合法状态
                {
                    if(a[i].s[j]&a[i-1].s[k]) continue;//上下两行不能有同一列号都种植玉米的情况 
                    f[i][j]+=f[i-1][k];//合法则累加
                }
        FORa(i,1,a[n].num) ans=(ans+f[n][i])%MOD;//累加答案 
        printf("%d",ans);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        FORa(i,1,n)
        {
            int t=0,x;
            FORa(j,1,m) scanf("%d",&x),t=(t<<1)+1-x;
            /*要符合这片土地是否可以种植 
            原本是为0的不能种植,但因为位运算的一些操作是对于1敏感
            所以此处有一种特殊的解决方法,就是将土地初始状态反向转化,0变成1,1变成0
            所以与现在枚举的状态如果有交集,直接忽略*/ 
            Pretreatment(i,t); 
        }
        Dp();
        return 0;
    }
    inline int read()
    {
        register char c(gc);register int f(1),x(0);
        while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
        return x*f;
    }
    /*2 3
    1 1 1
    0 1 0*/

    总结:

      1.DP状态的确定

      2.预处理筛选不合法状态

  • 相关阅读:
    尝试实现一个简单的C语言string类型
    LeetCode.49
    Python学习 —— 实现简单的爬虫
    图表可视化表达的逻辑原理
    颜色参数
    Python交互图表可视化Bokeh:7. 工具栏
    Python交互图表可视化Bokeh:6. 轴线| 浮动| 多图表
    Python交互图表可视化Bokeh:5 柱状图| 堆叠图| 直方图
    Python交互图表可视化Bokeh:4. 折线图| 面积图
    Python交互图表可视化Bokeh:3. 散点图
  • 原文地址:https://www.cnblogs.com/SeanOcean/p/11355774.html
Copyright © 2020-2023  润新知