bzoj3109(dfs,算是练了练代码能力)

输出格式错误了一发,导致没有1A,真是可惜;

所以比赛的时候要注意,像输出好几行的情况,注意每行末尾应该是空格还是\n,一定要注意细节啊

 

这道题,有写代码题的感觉了,在写的过程中及时写备注,要理清楚自己的思路再敲键盘

 

关于做法:

首先我一个格子如果因为大小号被束缚了,那么一定是它上面和左边的影响了它,所以只需要考虑上和左就可以了

map[12][12][2];//[0]up,[1]left,1small than,2 large than,最后一维0表示上面的关系,1表示左面的关系,这个值如果是0则两者没有束缚关系

如果是1,则这个点小于那个点,如果是2则大于那个点

还有,尽量把程序写的简洁易懂,不易出错;

位运算版1164ms

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int id[10][10]={0,0,0,0,0,0,0,0,0,0,
					  0,1,1,1,2,2,2,3,3,3,
					  0,1,1,1,2,2,2,3,3,3,
					  0,1,1,1,2,2,2,3,3,3,
					  0,4,4,4,5,5,5,6,6,6,
					  0,4,4,4,5,5,5,6,6,6,
					  0,4,4,4,5,5,5,6,6,6,
					  0,7,7,7,8,8,8,9,9,9,
					  0,7,7,7,8,8,8,9,9,9,
					  0,7,7,7,8,8,8,9,9,9};
int xx[12],yy[12],zz[12];
int map[12][12][2];//[0]up,[1]left,1small than,2 large than
int a[12][12];
bool end;
char get()
{
	char ch;
	ch='\0';
	while (ch!='^'&&ch!='>'&&ch!='<'&&ch!='v') scanf("%c",&ch);
	return ch;
}
void init()
{
	char ch;
	for (int k=1;k<=3;k++)
	{
		for (int i=1;i<=3;i++)
		{
			ch=get();
			if (ch=='>') map[(k-1)*3+1][(i-1)*3+2][1]=1;
			else map[(k-1)*3+1][(i-1)*3+2][1]=2;
			ch=get();
			if (ch=='>') map[(k-1)*3+1][(i-1)*3+3][1]=1;
			else map[(k-1)*3+1][(i-1)*3+3][1]=2;
		}//三层,各第一行的单独输入
		for (int i=2;i<=3;i++)
		{
			for (int j=1;j<=9;j++)
			{
				ch=get();
				if (ch=='^') map[(k-1)*3+i][j][0]=2;
				else map[(k-1)*3+i][j][0]=1;
			}//输入与上一层的关系 
			for (int j=1;j<=3;j++)
			{
				ch=get();
				if (ch=='>') map[(k-1)*3+i][(j-1)*3+2][1]=1;
				else map[(k-1)*3+i][(j-1)*3+2][1]=2;
				ch=get();
				if (ch=='>') map[(k-1)*3+i][(j-1)*3+3][1]=1;
				else map[(k-1)*3+i][(j-1)*3+3][1]=2;
			}//与左边的关系 
		}//每层中,剩下两行的输入 
	}
}
void debug()
{
	for (int i=1;i<=9;i++)
		for (int j=1;j<=9;j++) printf("%d %d up:%d left:%d\n",i,j,map[i][j][0],map[i][j][1]);
}
void write()
{
	for (int i=1;i<=9;i++)
	{
		for (int j=1;j<=8;j++) printf("%d ",a[i][j]);
		printf("%d\n",a[i][9]);
	}
}
void dfs(int x,int y)
{
	if (y==10) x++,y=1;
	if (x==10) {end=true;write();return ;}
	int l=1,r=9;
	if (map[x][y][0])
	{
		if (map[x][y][0]==1) r=a[x-1][y]-1;
		else l=a[x-1][y]+1;
	}
	if (map[x][y][1])
	{
		if (map[x][y][1]==1) r=min(r,a[x][y-1]-1);
		else l=max(l,a[x][y-1]+1);
	}//答案的可搜索区间 
	int u=xx[x]&yy[y]&zz[id[x][y]];
	for (int i=l;i<=r;i++) if (u&(1<<(i-1)))
	{
		xx[x]^=(1<<(i-1));
		yy[y]^=(1<<(i-1));
		zz[id[x][y]]^=(1<<(i-1));
		a[x][y]=i;
		dfs(x,y+1);
		if (end) return;
		xx[x]^=(1<<(i-1));
		yy[y]^=(1<<(i-1));
		zz[id[x][y]]^=(1<<(i-1));
	}
}
int main() 
{
	init();
	//debug();
	end=false;
	for (int i=1;i<=9;i++) xx[i]=yy[i]=zz[i]=(1<<9)-1;
	dfs(1,1);
	return 0;
}

数组判重的1396ms

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int id[10][10]={0,0,0,0,0,0,0,0,0,0,
					  0,1,1,1,2,2,2,3,3,3,
					  0,1,1,1,2,2,2,3,3,3,
					  0,1,1,1,2,2,2,3,3,3,
					  0,4,4,4,5,5,5,6,6,6,
					  0,4,4,4,5,5,5,6,6,6,
					  0,4,4,4,5,5,5,6,6,6,
					  0,7,7,7,8,8,8,9,9,9,
					  0,7,7,7,8,8,8,9,9,9,
					  0,7,7,7,8,8,8,9,9,9};
int xx[12][12],yy[12][12],zz[12][12];
int map[12][12][2];//[0]up,[1]left,1small than,2 large than
int a[12][12];
bool end;
char get()
{
	char ch;
	ch='\0';
	while (ch!='^'&&ch!='>'&&ch!='<'&&ch!='v') scanf("%c",&ch);
	return ch;
}
void init()
{
	char ch;
	for (int k=1;k<=3;k++)
	{
		for (int i=1;i<=3;i++)
		{
			ch=get();
			if (ch=='>') map[(k-1)*3+1][(i-1)*3+2][1]=1;
			else map[(k-1)*3+1][(i-1)*3+2][1]=2;
			ch=get();
			if (ch=='>') map[(k-1)*3+1][(i-1)*3+3][1]=1;
			else map[(k-1)*3+1][(i-1)*3+3][1]=2;
		}//三层,各第一行的单独输入
		for (int i=2;i<=3;i++)
		{
			for (int j=1;j<=9;j++)
			{
				ch=get();
				if (ch=='^') map[(k-1)*3+i][j][0]=2;
				else map[(k-1)*3+i][j][0]=1;
			}//输入与上一层的关系 
			for (int j=1;j<=3;j++)
			{
				ch=get();
				if (ch=='>') map[(k-1)*3+i][(j-1)*3+2][1]=1;
				else map[(k-1)*3+i][(j-1)*3+2][1]=2;
				ch=get();
				if (ch=='>') map[(k-1)*3+i][(j-1)*3+3][1]=1;
				else map[(k-1)*3+i][(j-1)*3+3][1]=2;
			}//与左边的关系 
		}//每层中,剩下两行的输入 
	}
}
void debug()
{
	for (int i=1;i<=9;i++)
		for (int j=1;j<=9;j++) printf("%d %d up:%d left:%d\n",i,j,map[i][j][0],map[i][j][1]);
}
void write()
{
	for (int i=1;i<=9;i++)
	{
		for (int j=1;j<=8;j++) printf("%d ",a[i][j]);
		printf("%d\n",a[i][9]);
	}
}
void dfs(int x,int y)
{
	if (y==10) x++,y=1;
	if (x==10) {end=true;write();return ;}
	int l=1,r=9;
	if (map[x][y][0])
	{
		if (map[x][y][0]==1) r=a[x-1][y]-1;
		else l=a[x-1][y]+1;
	}
	if (map[x][y][1])
	{
		if (map[x][y][1]==1) r=min(r,a[x][y-1]-1);
		else l=max(l,a[x][y-1]+1);
	}//答案的可搜索区间 
	for (int i=l;i<=r;i++) if (xx[x][i]==0&&yy[y][i]==0&&zz[id[x][y]][i]==0)
	{
		xx[x][i]=yy[y][i]=zz[id[x][y]][i]=1;
		a[x][y]=i;
		dfs(x,y+1);
		if (end) return;
		xx[x][i]=yy[y][i]=zz[id[x][y]][i]=0;
	}
}
int main() 
{
	init();
	//debug();
	end=false;
	dfs(1,1);
	return 0;
}


 



 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值