POJ 1038 Bugs Integrated, Inc.

Description

Bugs Integrated, Inc. is a major manufacturer of advanced memory chips. They are launching production of a new six terabyte Q-RAM chip. Each chip consists of six unit squares arranged in a form of a 2*3 rectangle. The way Q-RAM chips are made is such that one takes a rectangular plate of silicon divided into N*M unit squares. Then all squares are tested carefully and the bad ones are marked with a black marker.

Finally, the plate of silicon is cut into memory chips. Each chip consists of 2*3 (or 3*2) unit squares. Of course, no chip can contain any bad (marked) squares. It might not be possible to cut the plate so that every good unit square is a part of some memory chip. The corporation wants to waste as little good squares as possible. Therefore they would like to know how to cut the plate to make the maximum number of chips possible.
Task
You are given the dimensions of several silicon plates and a list of all bad unit squares for each plate. Your task is to write a program that computes for each plate the maximum number of chips that can be cut out of the plate.

Input

The first line of the input file consists of a single integer D (1 <= D <= 5), denoting the number of silicon plates. D blocks follow, each describing one silicon plate. The first line of each block contains three integers N (1 <= N <= 150), M (1 <= M <= 10), K (0 <= K <= MN) separated by single spaces. N is the length of the plate, M is its height and K is the number of bad squares in the plate. The following K lines contain a list of bad squares. Each line consists of two integers x and y (1 <= x <= N, 1 <= y <= M) ?coordinates of one bad square (the upper left square has coordinates [1, 1], the bottom right is [N,M]).

Output

For each plate in the input file output a single line containing the maximum number of memory chips that can be cut out of the plate.

Sample Input

2
6 6 5
1 4
4 6
2 2
3 6
6 4
6 5 4
3 3
6 1
6 2
6 4

Sample Output

3
4

首先,这是一道好(神)题。

用三进制表示是毫无疑问的(比两个二进制效率高多了)。

方法一:

介绍一种错误想法(极限数据7s)

枚举前两行的状态,和第三行的期望状态。

之后将三进制数转换成数组,进行判断和状态的更新。

要重构代码了,伤心。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int T,n,m,k,a[1005],b[1005],p[15],ans,mp[155][15],t1[101],t2[101],f[11][60005],rs;
void dfs(int num,int lst,int at,int bt)
{
	int att,btt;
	if(num==m)
	{
		ans++;
		a[ans]=at;
		b[ans]=bt;
		return ;
	}
	dfs(num+1,lst,at,bt);//不放 
	if(num-lst>=3)//横着放 
	{
		att=at+p[num-2]+p[num-1]+p[num];
		btt=bt+1;
		dfs(num+1,num,att,btt);
	}
	if(num-lst>=2)//竖着放 
	{
		att=at+2*p[num-1]+2*p[num];
		btt=bt+1;
		dfs(num+1,num,att,btt);
	}
}
void init(int x,int y)
{
	for(int i=1;i<=m;i++)
		t1[i]=x%3,x/=3;
	for(int i=1;i<=m;i++)
		t2[i]=y%3,y/=3;
}
bool check(int x)
{
	for(int i=1;i<=m;i++)
	{
		if(mp[x][i]==1&&t1[i]>0)
			return 0;
		if((t1[i]==1&&t2[i]==2)||(t1[i]==2&&t2[i]>=1))
			return 0;
	}
	return 1;
}
int calc(int x)
{
	int res=0;
	for(int i=1;i<=m;i++)
	{
		if(mp[x][i]==1||t1[i]>0)
			res+=2*p[i-1];
		else if(t2[i]==2)
			res+=p[i-1];
	}
	return res;
}
int main()
{
	p[0]=1;
	for(int i=1;i<=10;i++)
		p[i]=3*p[i-1];//处理3的幂 
	scanf("%d",&T);
	while(T--)
	{
		rs=0;
		ans=0;
		memset(mp,0,sizeof(mp));
		memset(f,-0x3f,sizeof(f));
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		scanf("%d%d%d",&n,&m,&k);
		while(k--)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			mp[x][y]=1;
		}
		dfs(0,-1,0,0);
		f[0][p[m]-1]=0;
		int end=p[m]-1;
		for(int i=1;i<=n;i++)//行 
		{
			for(int j=0;j<=end;j++)//前两行 
				if(f[(i&1)^1][j]>=0)
					for(int k=1;k<=ans;k++)//这一行 
					{
						init(a[k],j);
						if(check(i))//与坏点不冲突且前两行满足这一行 
						{
							int q=calc(i);
							f[i&1][q]=max(f[i&1][q],f[(i&1)^1][j]+b[k]);
							rs=max(rs,f[i&1][q]);
						}
					}
			memset(f[(i&1)^1],-0x3f,sizeof(f[(i&1)^1]));
		}
		printf("%d\n",rs);
	}
	return 0;
}

方法二:

枚举第(i-1)行的状态,与坏点合并,得到第i行什么也不放时的状态。

接着用他们搜索,同时更新状态。


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int T,n,m,k,mp[155][15],pow[15],f[2][60005],ans;
int calc1(int x,int y)
{
	int res=0;
	for(int i=1;i<=m;i++)
	{
		int t=(y%pow[i])/pow[i-1];
		if(mp[x][i]==1)
			res+=2*pow[i-1];
		else
			res+=((t==0)?0:(t-1)*pow[i-1]);
	}
	return res;
}
int calc2(int x,int y)
//取x的第(y-1)位 
{
	return (x%pow[y])/pow[y-1];
}
void dfs(int x,int y,int p,int q,int res)
//x行,y列,p i-1行,q i行 ,res这一行放置矩形的个数 
{
	if(y==m+1)
	{
		f[x][q]=max(f[x][q],f[x^1][p]+res);
		return ;
	}
	int qq;
	dfs(x,y+1,p,q,res);//不放 
	if(y>=3&&calc2(q,y)==0&&calc2(q,y-1)==0&&calc2(q,y-2)==0)//横着放 
	{
		qq=q+2*pow[y-1]+2*pow[y-2]+2*pow[y-3];
		f[x][qq]=max(f[x][qq],f[x^1][p]+res+1);
		ans=max(ans,f[x][qq]);
		dfs(x,y+1,p,qq,res+1);
	}
	if(y>=2&&calc2(p,y)==0&&calc2(p,y-1)==0&&calc2(q,y)==0&&calc2(q,y-1)==0)
	{
		qq=q+2*pow[y-1]+2*pow[y-2];
		f[x][qq]=max(f[x][qq],f[x^1][p]+res+1);
		ans=max(ans,f[x][qq]);
		dfs(x,y+1,p,qq,res+1);
	}
}
int main()
{
	pow[0]=1;
	for(int i=1;i<=10;i++)
		pow[i]=3*pow[i-1];
	scanf("%d",&T);
	while(T--)
	{
		ans=0;
		memset(f,-1,sizeof(f));
		scanf("%d%d%d",&n,&m,&k);
		memset(mp,0,sizeof(mp));
		while(k--)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			mp[x][y]=1;
		}
		int end=pow[m]-1;
		f[0][end]=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<=end;j++)
				if(f[(i&1)^1][j]>=0)
				{
					int q=calc1(i,j);
					dfs(i&1,1,j,q,0);
				}
			memset(f[(i&1)^1],-1,sizeof(f[(i&1)^1]));
		}
		printf("%d\n",ans);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值