Bugs IntegratedInc poj 1038

经典的状态压缩dp每个格子分三种状态(下面的格子为当前格),如图所示,分别用0,1,2表示


然后利用上一行的合法状态推导出当前行的一个基本状态(黑书上有详解),在该基本状态上,枚举可能的方案,更新表格

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string> 
#include <sstream>
#include <utility>   
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::greater;
using std::endl;

const int INFI((INT_MAX-1) >> 1);
const int MAXN(160);
const int MAXM(11);

bool mp[MAXN][MAXM];
int table[2][60000];
int pow3[12];
int N, M, K;
int cur, last;

int as1[11], as2[11];

void updata(int n, int st1, int &st2)
{
	st2 = 0;
	for(int i = 0; i < M; ++i)
	{
		as1[i] = st1%3;
		if(mp[n][i])
		{
			if(as1[i] == 2)
			{
				as2[i] = 1;
				st2 += 1*pow3[i];
			}
			else
			{
				as2[i] = 0;
				st2 += 0;
			}
		}
		else
		{
			as2[i] = 2;
			st2 += 2*pow3[i];
		}
		st1 /= 3;
	}
}

void dfs(int n, int m, int st, int value)
{
	if(value > table[cur][st])
		table[cur][st] = value;
	if(m <= M-2 && as2[m] == 0 && as2[m+1] == 0 && as1[m] == 0 && as1[m+1] == 0)
	{
		as2[m] = 2;
		as2[m+1] = 2;
		dfs(n, m+2, st+pow3[m]*2+pow3[m+1]*2, value+1);
		as2[m] = 0;
		as2[m+1] = 0;
	}
	if(m <= M-3 && as2[m] == 0 && as2[m+1] == 0 && as2[m+2] == 0)
	{
		as2[m] = 2;
		as2[m+1] = 2;
		as2[m+2] = 2;
		dfs(n, m+3, st+pow3[m]*2+pow3[m+1]*2+pow3[m+2]*2, value+1);
		as2[m] = 0;
		as2[m+1] = 0;
		as2[m+2] = 0;
	}
	if(m <= M-1)
		dfs(n, m+1, st, value);
}

int main()
{
	pow3[0] = 1;
	for(int i = 1; i <= 11; ++i)
		pow3[i] = pow3[i-1]*3;
	int T;
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d%d%d", &N, &M, &K);
		memset(mp, 0, sizeof(mp));
		for(int i = 1; i <= N; ++i)
			for(int j = 0; j < M; ++j)
				mp[i][j] = true;
		int x, y;
		for(int i = 0; i < K; ++i)
		{
			scanf("%d%d", &x, &y);
			mp[x][y-1] = false;
		}
		cur = 0;
		last = 1;
		memset(table[last], -1, sizeof(table[last]));
		int temp = 0;
		for(int i = 0; i < M; ++i)
			if(mp[1][i])
				temp += pow3[i]*1;
			else
				temp += pow3[i]*2;
		table[last][temp] = 0;
		for(int i = 2; i <= N; ++i)
		{
			memset(table[cur], -1, sizeof(table[cur]));
			for(int j = 0; j < pow3[M]; ++j)
				if(table[last][j] != -1)
				{
					int st2;
					updata(i, j, st2);
					dfs(i, 0, st2, table[last][j]);
				}
			cur ^= 1;
			last ^= 1;
		}
		int ans = 0;
		for(int i = 0; i < pow3[M]; ++i)
			if(table[last][i] > ans)
				ans = table[last][i];
		printf("%d\n", ans);
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值