51nod 1608 管道安装

51nod 链接   点击打开链接

codeforces 115C 链接  点击打开链接


本题求放置水管的方式的总数。管道就4个,而且管道的出口都是一边竖直一边水平。

分析后可以发现,水平方向与竖直方向可以分离开来进行考虑。


对于特定的一种放置管道的方式,可以按如下方式进行转化为0,1矩阵:

只考虑竖直: 令向上开口为0,向下为1,则化为0,1的一个矩阵。 上下方向0,1交替出现。

只考虑水平:同样可以得到一个矩阵,有同样的性质。


考虑这两种方式:   放置管道方式 可以 唯一确定 0,1矩阵。

反之, 竖直+水平0,1矩阵 也可以唯一确定 某种放置管道方式。

因此两者是一一对应关系,种数相等。


因此转化为求0,1矩阵的种数。由于0,1矩阵的交替出现的性质,上下01矩阵,某一列出现一个0,1即可确定该列。


因此最终结果只要求未被确定的行数+列数,即可2^(行数+列数)。同时注意可能有矛盾,此时答案为0。


算法实现就是读入初始已给定pattern,统计已确定与未确定的行列即可。

复杂度O(n*m)


#include<cstdio>
#include <cstdlib>
#define maxlen 500001
#define module 1000003
int n, m, figure, myresult = 0;
char ch;
char orientation[maxlen], orientation_row;

inline void GetMyPowerMod(int x, int &y)
{
	__int64 result = 1, tmp1 = x;
	while (y)
	{
		if (y & 1) { result = (result * tmp1) % module; }
		y >>= 1;
		tmp1 = (tmp1 * tmp1) % module;
	}
	printf("%d", result);
}

inline void exit_pro()
{
	printf("0");
	exit(0);
}

int main()
{
	scanf("%d%d", &n, &m);
	getchar();
	//cout << "啦啦啦" << flag << endl;
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < m; ++j)
		{
			scanf("%c", &ch);
			//printf("%c", ch);
			if (ch != '.')
			{
				if ((figure = ch - '1') > 1)
				{
					figure = 5 - figure;
				}

/*				if (f_row)								//行
				{
					//cout << j << '\t' << ((((figure & 2) >> 1) + j) & 1) << '\t' << orientation_row << endl;
					if (orientation_row != (((figure & 2) >> 1)^(j&1)))
					{
						exit_pro();
					}
				}
				else
				{
					orientation_row = ((((figure & 2) >> 1) ^ (j & 1)));
					f_row = true;
				}*/
				orientation_row |= (1 << ((((figure & 2) >> 1) ^ (j & 1))));
				orientation[j] |= (1 << ((figure & 1) ^ (i & 1)));
				//cout << f_row << '\t' << orientation[j] << endl;
			/*	if (f[j])								//行
				{
					//cout << i << '\t' << (((figure & 1) + i) & 1) <<'\t'<< orientation[j] << endl;
					if (orientation[j] != ((figure & 1) ^(i & 1)))
					{
						exit_pro();
					}
				}
				else
				{
				//	cout << i << '\t' << (((figure & 1) + i) & 1) << '\t' << orientation[j] << endl;
					orientation[j] = ((figure & 1) ^ (i & 1));
					f[j] = true;
				}*/
			}
		}
		
		getchar();
		if (orientation_row>2)
		{
			exit_pro();
		}
		myresult += (orientation_row == 0);
		//cout << f_row << '\t' << myresult << endl;
		//myresult = (myresult << (orientation_row == 0)) % module;
		orientation_row = 0;
	}

	//printf("\n%d", myresult);
	//cout << endl<<"kkkkkkkkk"<<flag << endl;

	for (int j = 0; j < m; ++j)
	{
		if (orientation[j] > 2)
		{
			exit_pro();
		}
		myresult += (orientation[j] == 0);
		//cout << orientation[j] << '\t' << myresult << endl;
		//myresult = (myresult << (orientation[j] == 0)) % module;
	}

	GetMyPowerMod(2, myresult);


	//printf("%d\n", myresult);
	return 0;
}
















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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值