• 【题解】洛谷P1879 [USACO06NOV] Corn Fields(状压DP)


    洛谷P1879:https://www.luogu.org/problemnew/show/P1879

    思路

    把题目翻译成人话

    在n*m的棋盘 每个格子不是0就是1

    1表示可以种 0表示不能种 相邻的格子不能同时种 求总方案数

    把每行看成一个n位的2进制数 预处理出每行的状态后 进行DP即可

    PS:在处理每行的初始状态时 将其取反后更好操作

    代码

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define mod 100000000
    int f[15][1010];
    int n,m,ans;
    struct State
    {
        int st[5000];
        int num;
    }a[15];
    void getstate(int i,int t)
    {
        int num=0;//记录此行有几种状态 
        for(int j=0;j<(1<<n);j++)//枚举所有状态 
        {
            if((j&t)||(j&(j<<1))||(j&(j>>1))) continue;//如果冲突就跳过 
            a[i].st[++num]=j;//记录状态 
            a[i].num=num;
        }
    }
    void dp()
    {
        for(int i=1;i<=a[1].num;i++) f[1][i]=1;//初始化 
        for(int i=2;i<=m;i++)//枚举行 
        {
            for(int j=1;j<=a[i].num;j++)//枚举第i行的状态 
            {
                f[i][j]=0;
                for(int k=1;k<=a[i-1].num;k++)//枚举第i-1行的状态 
                {
                    if(a[i].st[j]&a[i-1].st[k]) continue;//如果冲突就跳过 
                    f[i][j]+=f[i-1][k];//累计ans 
                }
            }
        }
        for(int i=1;i<=a[m].num;i++)
        ans=(ans+f[m][i])%mod;//累计第m行的所有状态的ans 
        printf("%d",ans);
    }
    int main()
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;i++)
        {
            int t=0;//处理当前行的状态 
            for(int j=1;j<=n;j++)
            {
                int x;
                cin>>x;//这里对输入进行取反操作 
                t=(t<<1)+1-x;//如1010 存成0101 方便后面判断状态 
            }
            getstate(i,t);//获得此行状态 
        }
        dp();
    }
  • 相关阅读:
    通过使用精简客户端,且不需要安装的客户端,配合PLSQL连接oracle数据库
    JDBC连接
    多线程TCP的socket通信
    基于UDP协议的socket通信
    基于TCP协议的socket通信
    设计模式之单例模式
    设计模式之代理模式
    设计模式之策略模式
    >hibernate-session中的方法
    >hibernate的四种状态
  • 原文地址:https://www.cnblogs.com/BrokenString/p/9812230.html
Copyright © 2020-2023  润新知