CF 472B Mystical Mosaic

37 篇文章 0 订阅
4 篇文章 0 订阅

刚开始的时候考虑过各种暴力,不过似乎都太复杂了以至于写着写着就出错了或者写不下去了。这题其实有非常简便的做法。对于矩阵中的每一列,如果在该列的某一行处是”#”,那么在选中该列的同时该行也是一定要同时选中的。那么,对于任意的两列i,j,如果他们需要选中的行一样,OK,没问题,这两列可以在同一次选择中被选中。但是,如果i,j需要选择的行不一样,那么他们肯定就不能在同一次中选择了,否则的话这两列肯定会多出来额外的“#”。那么,对于任意两列不是同一次选中的列,他们之间如果需要选中的行又有重复的话,那么肯定就不行了,因为每行只能被选中一次。最后,为了快速表示每一列的状态,我们可以用一个二进制数来表示。

#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<cstring>
#include<queue>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
ll hang[60];
int main()
{
    string mp[60];
    int n,m,i,j,k;
    cin>>n>>m;
    set<ll>s;
    for(i=1;i<=n;i++)cin>>mp[i];
    for(i=0;i<m;i++){
        for(j=1;j<=n;j++){
            if(mp[j][i]=='#')
                hang[i]|=(1ll<<j);//代表每一列需要的行的状态
        }
        s.insert(hang[i]);//去重
    }
    vector<ll>pos;
    for(auto j=s.begin();j!=s.end();j++){
        pos.push_back(*j);
    }
    for(i=0;i<pos.size()-1;i++){
        for(j=i+1;j<pos.size();j++){
            if(pos[i]&pos[j]){
                cout<<"NO"<<endl;return 0;
            }
        }
    }
    cout<<"YES"<<endl;

    return 0;
}

由于本题数据范围非常小,所以不查重暴力枚举也能过:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m;
ll a[60];
char s[60];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s+1);
        for(int j=1;j<=m;++j)
        a[i]=(a[i]<<1|(s[j]=='#'));
    }
    for(int i=1;i<=n;++i)
    for(int j=1+i;j<=n;++j)
    if((a[i]!=a[j])&&(a[i]&a[j]))
    {
        puts("No");
        return 0;
    }
    puts("Yes");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值