POJ 1038 Bugs Integrated Inc (复杂的状压DP)

\(POJ~1038~~*Bugs~Integrated~Inc:\) (复杂的状压DP)



\(solution:\)

很纠结的一道题目,写了大半天,就想练练手,结果这手生的。其实根据之前那道炮兵阵地就不应该写的,但是总觉得自己的思路会好一些,码量又小。

博主的核心思路其实就是用一个二进制数来压缩三行的状态,因为二进制的左移右移很方便。然后就是如果三进制会很不好转移。

  1. 我们可以用一个二进制数来预处理压缩出第 \(i\) 往下三行的障碍状态,前 \(m\) 个二进制位表第 \(i\) 行,中间 \(m\) 个二进制位表 \(i+1\) 行,后 \(m\) 个二进制位表第 \(i+2\) 行
  2. 我们设一个长方体用坐上角那个点表示
  3. 我们可以用搜索来搜出一行内的长方体放置方案,这个很好写,线面代码里唯一一个手写函数就是用来求这个的。它同样用一个二进制来表示出,这个方案里三行被长方体覆盖的状况。
  4. 然后我们需要用步骤3里的单行放置方案来求出上下两行的方案拼接方案(其实就是用一个二进制将两行的方案压缩进来)。直接暴力枚举单行放置方案,再用二进制与运算来判断是否有冲突:如下
  5.      for(rg i=1;i<=tt;++i)
                 for(rg j=1;j<=tt;++j)
                             if(!((b[i]>>m)&b[j])){
                                 r[++st]=j; p[i][j]=st; //r表示方案的下面一行用的那个单行方案
                                 g[st]=(b[i]>>m)|b[j]; //找出两行的放置方案
                             }
  6. 然后我们设状态就必须将前两行的状态都包含进去:设 \(f[i][j]\) 表示第 \(i\) 行前两行状态为 \(g[j]\) 意义在上面代码里
  7. 然后我们就可以开始常规转移,但是数组 \(r\) 和数组 \(p\) 一定要搞清楚!


\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define rg register int

using namespace std;

int n,m,ff,tt,st,ans;
int a[155];
int b[305];
int c[305];
int g[3005];
int r[3005];
int p[305][305];
int f[155][3005];

inline void dfs(int i,int v,int vv){ //用一个二进制表示一行的状态(在某一行放,下面两行都有可能被覆盖,用一个二进制将这三行压在一起)
    if(i==m){b[++tt]=v; c[tt]=vv; return ;} dfs(i+1,v,vv); //导入方案
    if(i+3<=m)dfs(i+3,v|(7<<i)|(7<<(i+m)),vv+1); //放入横的长方体
    if(i+2<=m)dfs(i+2,v|(3<<i)|(3<<(i+m)|(3<<(i+m+m))),vv+1); //放入竖的长方体
}

int main(){
    rg t; cin>>t;
    while(t--){
        cin>>n>>m>>ff; ans=0; //读入
        memset(a,0,sizeof(a));
        memset(f,0,sizeof(f));
        tt=0; st=0; dfs(0,0,0); //初始化
        for(rg i=1;i<=tt;++i)
            for(rg j=1;j<=tt;++j)
                if(!((b[i]>>m)&b[j])){
                    r[++st]=j; p[i][j]=st; //r表示方案的下面一行用的那个单行方案
                    g[st]=(b[i]>>m)|b[j]; //找出两行的放置方案
                }
        for(rg i=1;i<=ff;++i){
            rg x,y; cin>>x>>y;
            a[x]|=1<<(y-1);
        } a[n+1]=(1<<m)-1; //障碍的二进制读入,最后还要加一行障碍,防止长方体出界
        for(rg i=1;i<=n;++i){
            a[i]|=(a[i+1]<<m)|(a[i+2]<<(m+m)); //连续三行障碍压进一个二进制里
            for(rg j=1;j<=st;++j)
                for(rg k=1;k<=tt;++k)
                    if(!(((g[j]>>m)|a[i])&b[k])){ //这一行放的方案与前面的方案还有障碍不会冲突
                        f[i][p[r[j]][k]]=max(f[i][p[r[j]][k]],f[i-1][j]+c[k]);
                        ans=max(ans,f[i][p[r[j]][k]]); //因为多加了一行障碍,不用怕出界
                    }
        } printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/812-xiao-wen/p/11210405.html

时间: 2024-10-10 14:45:52

POJ 1038 Bugs Integrated Inc (复杂的状压DP)的相关文章

POJ 1038 Bugs Integrated, Inc. 状态压缩DP

题目来源:1038 Bugs Integrated, Inc. 题意:最多能放多少个2*3的矩形 思路:状态压缩DP啊 初学 看着大牛的代码搞下来的  总算搞懂了 接下来会更轻松吧 3进制代表前2行的状态(i行和i-1行)1代表i-1行占位 2代表i行占位 i-1不管有没有占位都不会影响的0代表i行和i-1行都空闲 然后枚举状态dfs更新状态 话说就不能没写深搜了 有点不会了 #include <cstdio> #include <cstring> #include <alg

POJ 题目2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13519   Accepted: 7876 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

【POJ 2411】Mondriaan&#39;s Dream(状压dp)

[POJ 2411]Mondriaan's Dream(状压dp) Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 14107   Accepted: 8152 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in hi

POJ 1038 Bugs Integrated, Inc.

AC通道 神坑的一道题,写了三遍. 两点半开始写的, 第一遍是直接维护两行的二进制.理论上是没问题的,看POJ discuss 上也有人实现了,但是我敲完后准备开始调了.然后就莫名其妙的以为会超时,就删掉了. 第二遍是想错了,因为和之前写过的一道题很像,那道题的正方形最中间不重合即可,所以我以为本质是一样的,然后按照那样的思路写.写写调调到五点半,样例搞掉后,提交,A2T7W1 然后随便找了组数组跟了一下,发现这个方块不允许重合导致这两道题的核心思路差别很大,所以删掉了. 第三遍开始按照自己想的

POJ 3311 Hie with the Pie (状压DP)

题意: 每个点都可以走多次的TSP问题:有n个点(n<=11),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短是多少? 思路: 同HDU 5418 VICTOR AND WORLD (可重复走的TSP问题,状压DP)这道题几乎一模一样. 1 //#include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #includ

POJ 1038 Bugs Integrated, Inc. ——状压DP

状压上面有几个方块,然后DFS转移. 复杂度貌似很高$3_{}^{20}*n$ 反正过了 #include <map> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i)

POJ 1038 Bugs Integrated, Inc.(状态压缩)

Bugs Integrated, Inc. Time Limit: 15000MS   Memory Limit: 30000K Total Submissions: 9088   Accepted: 3472 Case Time Limit: 5000MS Description Bugs Integrated, Inc. is a major manufacturer of advanced memory chips. They are launching production of a n

POJ 2923 【01背包+状态压缩/状压DP】

题目链接 Emma and Eric are moving to their new house they bought after returning from their honeymoon. Fortunately, they have a few friends helping them relocate. To move the furniture, they only have two compact cars, which complicates everything a bit.