ZOJ 3954 Seven-Segment Display (预处理/状态压缩)

这是2017浙大校赛的最后一道题(还有一道实在不会做),感觉并没有什么特别难的题目,写的题解好像在以后来看也没什么参考价值。。

题意

每一列作为一个元素,是否存在一个排列使得结果刚好是标准模式

思路

由于排列总共就 7! 种,直接打表就好了,但是因为组数较多,每次都 O(n) 查找会超时,所以可以将状态表示成一个整数(刚好63位,longlong能够存的下),每次二分找答案,由于存在空着的元组,所以排列变成 297! 种,但是每次搜索很快( log(297!) ),时间满足要求

代码

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define sc(a) scanf("%d",&a)
const int INF=0x3f3f3f3f;
const int maxn=2e5+50;
const int mod=1e9+7;
const double eps=1e-8;
#define pii pair<int,int>
typedef long long ll;
typedef unsigned int ui;
using namespace std;

int pattern[10][7]{
        0,0,0,0,0,0,0,
        1,0,0,1,1,1,1,
        0,0,1,0,0,1,0,
        0,0,0,0,1,1,0,
        1,0,0,1,1,0,0,
        0,1,0,0,1,0,0,
        0,1,0,0,0,0,0,
        0,0,0,1,1,1,1,
        0,0,0,0,0,0,0,
        0,0,0,0,1,0,0
};
char buf[10];
int s7[7];

int getXFromS7(int s7[]){
    int ret=0;
    for(int i=0;i<7;i++){
        if(s7[i]) ret+=1<<(6-i);
    }
    return ret;
}

struct Pattern{
    ll s[10];
    int getFrom(int perm[],int x){
        for(int i=0;i<7;i++){
            s7[i]=pattern[x][perm[i]];
        }
        return getXFromS7(s7);
    }
    void init(int perm[]){
        mem(s,0);
        rep(i,1,10) s[i]=getFrom(perm,i);
    }
    void print(){
        rep(i,1,10){
            printf("%lld ",s[i]);
        }
        puts("");
    }

    void read(){
        mem(s,0);
        int n; sc(n);
        rep(i,0,n){
            int x; sc(x);
            scanf(" %s",buf);
            rep(j,0,7){
                s7[j]=buf[j]-'0';
            }
            s[x]=getXFromS7(s7);
        }
    }

    ll toLL(){
        ll ret=0;
        rep(i,1,10){
            ret+=s[i]<<((i-1)*7);
        }
        return ret;
    }
};

set<ll> ans;
void getP(Pattern &p,int dep){
    if(dep==10) {
        //p.print();
        ans.insert(p.toLL());
        return;
    }
    ll tmp=p.s[dep];
    p.s[dep]=0;
    getP(p,dep+1);
    p.s[dep]=tmp;
    getP(p,dep+1);
}
void init(){
    int perm[7];
    rep(i,0,7) perm[i]=i;
    do{
        Pattern p;
        p.init(perm);
        //p.print();
        getP(p,1);
    }while(next_permutation(perm,perm+7));
    //for(auto i:ans) cout<<"= ="<<i<<endl;
}

Pattern tar;

int main()
{
#ifndef ONLINE_JUDGE
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif
    init();
    //printf("%d\n",ans.size());

    int T; scanf("%d",&T);
    while(T--){
        tar.read();
        puts(ans.find(tar.toLL())!=ans.end()?"YES":"NO");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值