poj1038 Bugs Integrated, Inc.

二进制状压练得挺熟, 但是一直没有时间好好研究三进制状压。

于是找了个题目学习了一下, 两天里修修补补总算AC了。

有几个收获。

1. 三进制与十进制的转换的小技巧(利用数组)

2. 刷表法时, 用dfs来更新状态。这种更新状态的方式蛮新颖的,我这种蒟蒻第一次遇见。

3. 还是更新状态。可以先把新状态算出来,再来枚举决策。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 150 + 5;
const int MAXM = 10  + 2;

int N, M, K;
bool badp[MAXN][MAXM];
int p[12] = {1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049};
int f[2][60000];

inline int threetoten(int a[]){
    int tmp = 0;
    for(int i = 0; i < M; i++)
        tmp += a[i] * p[i];
    return tmp;
}

inline void tentothree(int x, int a[]){
    for(int i = 0; i < M; i++)
        a[i] = x % 3, x /= 3;
}

int pre[13], cur[13];
void dfs(int d, int j, int last, int state)
{
    int k;
    f[d][state] = max(f[d][state], last);
    if(j >= M) return ;
    if((j + 1) < M && (pre[j] == 0) && (pre[j + 1] == 0) && (cur[j] == 0) && (cur[j + 1] == 0)){
        cur[j] = cur[j + 1] = 2;
        k = threetoten(cur);
        dfs(d, j + 2, last + 1, k);
        cur[j] = cur[j + 1] = 0;
    }
    if((j + 2) < M && (cur[j] == 0) && (cur[j + 1] == 0) && (cur[j + 2] == 0)){
        cur[j] = cur[j + 1] = cur[j + 2] = 2;
        k = threetoten(cur);
        dfs(d, j + 3, last + 1, k);
        cur[j] = cur[j + 1] = cur[j + 2] = 0;
    }
    dfs(d, j + 1, last, state);
    return ;
}

int solve()
{
    int d = 0; int tmp;
    memset(f[d], -1, sizeof(f[d]));
    for(int i = 0; i < M; i++) pre[i] = (badp[1][i] ? 2 : 1);
    tmp = threetoten(pre);
    f[d][tmp] = 0;

    for(int i = 2; i <= N; i++){
        d ^= 1;
        memset(f[d], -1, sizeof(f[d]));

        for(int j = 0; j < p[M]; j++){
            if(f[d ^ 1][j] == -1) continue;
            tentothree(j, pre);
            for(int k = 0; k < M; k++){
                if(badp[i][k]) cur[k] = 2;
                else cur[k] = (pre[k] == 0 ? 0 : pre[k] - 1);
            }

            tmp = threetoten(cur);
            dfs(d, 0, f[d ^ 1][j], tmp);
        }
    }
    int ans = 0;
    for(int i = 0; i < p[M]; i++) ans = max(ans, f[d][i]);
    return ans;
}

int main()
{
    int T; cin>>T;
    while(T--)
    {
        cin>>N>>M>>K;
        memset(badp, false, sizeof(badp));
        for(int i = 1, x, y; i <= K; i++){
            scanf("%d%d", &x, &y);
            badp[x][y - 1] = true;
        }
        printf("%d\n", solve());
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wsmrxc/p/9281425.html

时间: 2024-08-02 14:27:15

poj1038 Bugs Integrated, Inc.的相关文章

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 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 1038 Bugs Integrated Inc (复杂的状压DP)

\(POJ~1038~~*Bugs~Integrated~Inc:\) (复杂的状压DP) \(solution:\) 很纠结的一道题目,写了大半天,就想练练手,结果这手生的.其实根据之前那道炮兵阵地就不应该写的,但是总觉得自己的思路会好一些,码量又小. 博主的核心思路其实就是用一个二进制数来压缩三行的状态,因为二进制的左移右移很方便.然后就是如果三进制会很不好转移. 我们可以用一个二进制数来预处理压缩出第 \(i\) 往下三行的障碍状态,前 \(m\) 个二进制位表第 \(i\) 行,中间 \

POJ 1038 Bugs Integrated, Inc.

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

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)

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

有点点小虐心. #include <iostream> #include <cstring> #include <fstream> using namespace std; const int ternarys[12] = { 0, 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049 }; int DP[2][59049]; int bit_map[155][15]; int pre_line[15]; int now

北大ACM题库习题分类与简介(转载)

在百度文库上找到的,不知是哪位大牛整理的,真的很不错! zz题 目分类 Posted by fishhead at 2007-01-13 12:44:58.0 -------------------------------------------------------------------------------- acm.pku.edu.cn 1. 排序 1423, 1694, 1723, 1727, 1763, 1788, 1828, 1838, 1840, 2201, 2376, 23

ACM训练方案-POJ题目分类

ACM训练方案-POJ题目分类 博客分类: 算法 ACM online Judge 中国: 浙江大学(ZJU):http://acm.zju.edu.cn/ 北京大学(PKU):http://acm.pku.edu.cn/JudgeOnline/ 杭州电子科技大学(HDU):http://acm.hdu.edu.cn/ 中国科技大学(USTC):http://acm.ustc.edu.cn/ 北京航天航空大学(BUAA)http://acm.buaa.edu.cn/oj/index.php 南京

转载:poj题目分类(侵删)

转载:from: POJ:http://blog.csdn.net/qq_28236309/article/details/47818407 按照ac的代码长度分类(主要参考最短代码和自己写的代码) 短代码:0.01K–0.50K:中短代码:0.51K–1.00K:中等代码量:1.01K–2.00K:长代码:2.01K以上. 短:1147.1163.1922.2211.2215.2229.2232.2234.2242.2245.2262.2301.2309.2313.2334.2346.2348