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)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define mp make_pair
#define mask(i) ((mask%pow[i+1])/pow[i])
#define a(i) (a[x][i])
int dp[2][500005],pow[20],n,m,k;
int a[205][20],t,now,pre;
void print(int mask)
{F(i,0,m-1)printf("%d",(mask%pow[i+1])/pow[i]);}
void dfs(int x,int y,int mask,int val)
{
	if (y>=m){dp[pre][mask]=max(val,dp[pre][mask]);return;}
	if (y+2<m&&!a(y)&&!a(y+1)&&!a(y+2)&&mask(y)==mask(y+1)&&mask(y+1)==mask(y+2))
	{
		if (mask(y)==1)
		{
			mask-=pow[y]+pow[y+1]+pow[y+2];
			dfs(x,y+3,mask,val+1);
			mask+=pow[y]+pow[y+1]+pow[y+2];
		}
		else
		{
			mask+=pow[y]+pow[y+1]+pow[y+2];
			dfs(x,y+3,mask,val);
			mask-=pow[y]+pow[y+1]+pow[y+2];
		}
	}
	if (y+1<m&&!a(y)&&!a(y+1)&&mask(y)==mask(y+1))
	{
		if (mask(y)<2)
		{
			mask+=pow[y]+pow[y+1];
			dfs(x,y+2,mask,val);
			mask-=pow[y]+pow[y+1];
		}
		else
		{
			mask-=2*pow[y]+2*pow[y+1];
			dfs(x,y+2,mask,val+1);
			mask+=2*pow[y]+2*pow[y+1];
		}
	}
	if (!mask(y))
	{
		dfs(x,y+1,mask,val);
	}
}
int main()
{
	scanf("%d",&t);
	pow[0]=1;
	F(i,1,14)pow[i]=pow[i-1]*3;
	while (t--)
	{
		memset(a,0,sizeof a);
		scanf("%d%d%d",&n,&m,&k);
		F(i,1,k)
		{
			int x,y;scanf("%d%d",&x,&y);
			x--; y--;
			a[x][y]=1;
		}
		F(i,0,m-1) a[n][i]=1;
		now=1;pre=0;
		memset(dp[pre],-1,sizeof dp[pre]);
		dp[pre][0]=0;
		F(i,0,n)
		{
			now^=1; pre^=1;
			memset(dp[pre],-1,sizeof dp[pre]);
			F(j,0,pow[m]-1) if (~dp[now][j])
			{
				dfs(i,0,j,dp[now][j]);
			}
		}
		printf("%d\n",dp[pre][0]);
	}
}

  

时间: 2024-11-11 09:36:45

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

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

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

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

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

http://poj.org/problem?id=2411 求一个n*m矩阵用1*2方块去填满的情况有几种 思路:状压dp,先预处理那些状态之间能互相到达,情况就几种,上一个两个1,下一个状态也两个1,上一个为0,下一个必须为1,还有一种是上一个为1,下一个为0的情况 然后就一层层往后递推即可 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int

POJ 2411 Mondriaan&#39;s Dream ——状压DP 插头DP

[题目分析] 用1*2的牌铺满n*m的格子. 刚开始用到动规想写一个n*m*2^m,写了半天才知道会有重复的情况. So Sad. 然后想到数据范围这么小,爆搜好了.于是把每一种状态对应的转移都搜了出来. 加了点优(gou)化(pi),然后poj上1244ms垫底. 大概的方法就是考虑每一层横着放的情况,剩下的必须竖起来的情况到下一层取反即可. 然后看了 <插头DP-从入门到跳楼> 这篇博客,怒抄插头DP 然后16ms了,自己慢慢YY了一下,写出了风(gou)流(pi)倜(bu)傥(tong)

poj 2411 Mondriaan&#39;s Dream 状压dp入门

题意: 求h*w的矩形被1*2的小矩形覆盖的方案数. 分析: 状压dp入门,<挑战程序设计竞赛>上讲的很好,好几天才看懂. 代码: #include <iostream> using namespace std; __int64 ans[16][16]; int n,m; __int64 dp[2][1<<16]; __int64 solve() { int i,j,used; memset(dp,0,sizeof(dp)); __int64 *crt=dp[0],*n

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

题意:给出一个n*m的棋盘,及一个小的矩形1*2,问用这个小的矩形将这个大的棋盘覆盖有多少种方法. 析:对第(i,j)位置,要么不放,要么竖着放,要么横着放,如果竖着放,我们记第 (i,j)位置为0,(i+1,j)为1,如果横着放,那么我们记 (i,j),(i,j+1)都为1,然后dp[i][s]表示 第 i 行状态为 s 时,有多少方法,那么我们就可以考虑与和匹配的状态,这个也很容易判断. 代码如下: #pragma comment(linker, "/STACK:1024000000,102

POJ 1185 炮兵阵地(状压DP入门)

http://poj.org/problem?id=1185 状压DP: 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int dp[105][100][100]; 7 int ma[105],st[105]; 8 9 int ok(int x) 10 { 11 return (x&(x<<1))+(x&(x&

POJ 3254 Corn Fields 【状压DP】

[题目大意]一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一头牛都不放也是一种方案) [解析]根据题意,把每一行的状态用二进制的数表示,0代表不在这块放牛,1表示在这一块放牛.首先很容易看到,每一行的状态要符合牧场的硬件条件,即牛必须放在能放牧的方格上.这样就能排除一些状态.另外,牛与牛之间不能相邻,这样就要求每一行中不能存在两个相邻的1,这样也能排除很多状态.