习题:sajam(推理)

习题:

Milo正聚精会神的组建自己的圣诞集市,他将把这个集市组建成整个欧洲最好的圣诞集市。晚上结束,到关灯的时间了,但有些人相当无礼,并没有关掉桌上的灯。由于电费越来越贵,Milo希望所有的灯都能很快的关掉,为此,他使用了传奇电子平板电脑(LEET)来达到这个目的,但他同时也需要你的帮助。

Milo的圣诞集市有N行,每行有N个摊位。在LEET上,Milo有两个按钮:

·按下第一个按钮,Milo想象出第x行,然后打开已关闭的第x行的每个灯,同时关闭第x行的每个已经打开的灯。

·按下第二个按钮,Milo想象出第x列,然后打开已关闭的第x列的每个灯,同时关闭第x列的每个已经打开的灯。

通过按压自己的肚脐(第三个按钮),Milo将决定走到一个特定的摊位,并亲自打开(或关闭)这个摊位的灯。现在的问题是,他的腿受伤了,为了避免肺栓塞,医生规定他“第三个按钮”最多只能使用K次(K≤N),幸运的是,第一个按钮和第二个按钮可以无限次使用。

请问,Milo有没有可能关掉所有摊位上的灯。

输入格式

第一行输入两个数N和K,表示摊位的行数和Milo能够使用第三个按钮的个数。(1≤N≤1000,0≤K≤N)

接下来的N行,每行N个字母,这些字母由‘x’和‘o’组成,其中,‘x’表示这个摊位的灯已经关闭,‘o’表示这个摊位的灯还开着。

输出格式

如果所有的灯能够全部关闭,输出“DA”。否则,输出“NE”。

样例

样例输入1

2 0
ox
ox

样例输出1

DA

样例输入2

3 1
ooo
xoo
oox

样例输出2

NE

样例输入3

4 2
oxxo
xxox
oxoo
oxxo

样例输出3

DA

思路:
首先有一点我们是可以明确的,第一个操作针对一行只会使用一次,第二个操作针对一列只会使用一次,第三个操作针对每一个格子只会使用一次。明白这点之后,我们再次考虑两行的状态,将这两行转换成二进制,再进行异或,如果异或后这一位为0,则证明这两个灯状态是一样的,说明我们不需要对这两个灯进行第三个操作,反之,则需要进行,同时这个操作是必须进行的。

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int k;
int tot;
char c[1005][1005];
bool f=0;
bitset<1005> a[1005];
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
		cin>>(c[i]+1);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(c[i][j]=='o')
				a[i].set(j);
		}
	}
	if(k==n)
	{
        for(int i=1;i<=n;i++)
        {
            a[1].flip(i);
            int flag=0;
            for(int j=2;j<=n;j++)
            {
                a[0]=a[1]^a[j];
                int tmp=B[0].count();
                if(min(tmp,n-tmp)!=1) 
                {
                    flag=1;
                    break;
                }
            }
            if(!flag)
			{
				cout<<"DA";
                return 0;
            }
            a[1].flip(i);
        }
    }
	for(int i=1;i<=n;i++)
	{
		int s=0;
		for(int j=i+1;j<=n;j++)
		{
			a[0]=a[i]^a[j];
			s=s+min(a[0].count(),n-a[0].count());
		}
		if(s<=k)
		{
			f=1;
			break;
		}
	}
	if(f)
		cout<<"DA";
	else
		cout<<"NE";
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值