zoukankan      html  css  js  c++  java
  • [NOI2000]算符破译

    NOI2000的题吓死人啊。

    一开始写了一个裸的搜索,发现样例跑的都有点吃力。然后弃疗了。

    看完题解后觉得其实优化也不是很难想。

    显然先枚举=+*。然后每一行之前没出现过的字符就暴力枚举对应的数字。

    这样做不加剪枝是过不了的。

    然后有一个显然的优化是,=+*这三个确定后一块块数字的位数也就确定了。

    对于每一行,我们算出左右两边的可能的答案位数范围,然后判断有无交集,没有就不合法。

    然后就能过了?

    当然,还有一些,比如说当前搜下去不会对答案产生变动就剪枝。

    其实还可以加上如从低位到高位搜,然后确定低位,不合法就剪枝。但感觉这个有点烦就没加。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<vector>
    #include<map>
    #include<queue>
    #include<string>
    #include<bitset>
    #include<iomanip>
    #include<iostream>
    #include<cmath>
    using namespace std;
    #define rep(i,x,y) for(i=x;i<=y;i++)
    #define _rep(i,x,y) for(i=x;i>=y;i--)
    #define REP(i,x,y) for(int i=(x);i<=(y);i++)
    #define _REP(i,x,y) for(int i=(x);i>=(y);i--)
    #define CL(S,x) memset(S,x,sizeof(S))
    #define CP(S1,S2) memcpy(S1,S2,sizeof(S2))
    #define ALL(x,S) for(__typeof((v).end()) x=S.begin();x!=S.end();x++)
    #define pb push_back
    #define IN insert
    #define ER erase
    #define BE begin()
    #define ED end() 
    #define LB lower_bound
    #define UB upper_bound
    #define mp make_pair
    #define fi first
    #define se second
    #define upmin(x,y) x=min(x,y)
    #define upmax(x,y) x=max(x,y)
    #define COUT(S,x) cout<<fixed<<setprecision(x)<<S<<endl
    template<class T> inline void read(T&x){bool fu=0;char c;for(c=getchar();c<=32;c=getchar());if(c=='-')fu=1,c=getchar();for(x=0;c>32;c=getchar())x=x*10+c-'0';if(fu)x=-x;};
    template<class T> inline void read(T&x,T&y){read(x);read(y);}
    template<class T> inline void read(T&x,T&y,T&z){read(x);read(y);read(z);}
    inline char getc(){char c;for(c=getchar();c<=32;c=getchar());return c;}
    
    typedef long long ll;
    typedef long double ld;
    typedef pair<int,int> pii;
    
    const int inf=int(1e9);
    int T,n,i,j,k,l,p,c;
    char a[1111][13];int len[1111];
    int w[15];int cnt[13][1111];
    bool c2[15],c1[15];int lg2[(1<<10)+10];
    int ans[15];
    int st[15];bool mark[15];
    bool near[128][128];
    char eq,mul,add;bool sol;
    
    bool caneq()
    {
        CL(c1,1);
        for(char c='a';c<='m';c++)
        rep(i,1,T)
    	{
    		bool can2=1;
    		rep(j,1,len[i])
    		{
                if(j<len[i])near[a[i][j]][a[i][j+1]]=near[a[i][j+1]][a[i][j]]=1;
    			if(a[i][j]==c)cnt[c-'a'][i]++;
    		}
    		if(cnt[c-'a'][i]!=1)can2=0;
    		if(a[i][1]==c||a[i][len[i]]==c){c1[c-'a']=0;can2=0;}
    		c2[c-'a']=can2;
    	}
    }
    
    bool D(int x){return x>=0;}
    int cl()
    {
    	int i,tot=0;
    	for(;mark[st[0]-1];st[0]--)
    		st[st[0]-1]=st[st[0]-1]*st[st[0]];
    	rep(i,1,st[0])tot+=st[i];st[0]=0;
    	return tot;
    }
    bool check(int d)
    {
    	int i,j,k,la=-1,left=-1,right=-1;st[0]=0;
    	rep(i,1,len[d])
    	{
    		int c=w[a[d][i]-'a'];
    		if(D(c))
    			if(D(la))st[st[0]]=st[st[0]]*10+c;
    			else st[++st[0]]=c;
    		else
    		{
    			if(st[0]==0)return 0;
    			for(;mark[st[0]-1];st[0]--)
    				st[st[0]-1]=st[st[0]-1]*st[st[0]];
    			if(c==-3)mark[st[0]]=1;
    			else if(c==-1)left=cl();
    			else mark[st[0]]=0;
    		}
    		la=c;
    	}
    	right=cl();
    	return left==right;
    }
    
    void go(int d,int nl,int S) //dfs
    {
        bool ppp=1;rep(i,0,12)if(!(ans[i]==w[i]||ans[i]==-200)){ppp=0;break;}if(ppp)return;
    	if(d>T)
    	{    
            //rep(i,0,12) printf("%c : %d
    ",'a'+i,w[i]);printf("end
    ");
            sol=1;
    		rep(i,0,12)if(w[i]!=inf)
    		{
    		      if(ans[i]==-100)ans[i]=w[i];
    		      else if(ans[i]!=w[i])ans[i]=-200;
            }
            else ans[i]=-200;
    		return;
    	}
    	else
    	{
    		if(nl>len[d])
    		{
    			if(check(d))
                    go(d+1,1,S);
    			return;
    		}
    		int cc=a[d][nl]-'a';
    		if(w[cc]==inf)
    		{
    			for(int S2=S;S2;S2-=S2&-S2)
    			{
    				int t=lg2[S2&-S2];
    				if(nl==1&&t==0&&w[a[d][2]-'a']>0)continue;
    				w[cc]=t;
    				go(d,nl+1,S-(S2&-S2));
    				w[cc]=inf;
    			}
    		}
    		else go(d,nl+1,S);
    	}
    }
    void print()
    {
        int i;
        rep(i,0,12)
    	if(ans[i]>=-3)
    	{
    		putchar('a'+i);
    		if(ans[i]==-3)putchar('*');
    		else if(ans[i]==-2)putchar('+');
    		else if(ans[i]==-1)putchar('=');
    		else putchar('0'+ans[i]);
    		putchar('
    ');
    	}
    	if(!sol)printf("noway
    ");
    }
    
    int g,lw[15],rw[15];
    void clw(int&L,int&R){L=R=0;for(;g;g--)upmax(L,lw[g]),R=max(rw[g],R)+(R>0);}
    bool predfs()
    {
        int d,i,j,la,Llw,Lrw,Rlw,Rrw;
        rep(d,1,T){
            g=0;la=-1;
            rep(i,1,len[d]){
        		int c=w[a[d][i]-'a'];
        		if(c==inf){if(la<0)g++,lw[g]=rw[g]=0;lw[g]++;rw[g]++;}
        		else{
                    if(g==0)return 0;
        			for(;mark[g-1];g--)  lw[g-1]+=lw[g]-1,rw[g-1]+=rw[g];
        			if(c==-3)mark[g]=1;
        			else if(c==-2)mark[g]=0;
                    else if(c==-1)clw(Llw,Lrw);
        		}
        		la=c;
        	}
        	clw(Rlw,Rrw);
            if(Lrw<Rlw||Rrw<Llw)
            {
                return 0;
            }
        }
        return 1;
    }
    
    int main()
    {
        //freopen("eqution.in","r",stdin);freopen("eqution.out","w",stdout);
        
    	read(T);rep(i,1,T)scanf("%s",a[i]+1),len[i]=strlen(a[i]+1);
    	
    	rep(i,0,10)lg2[1<<i]=i;
    	
    	caneq();
    
    	rep(i,0,12)ans[i]=-100;
    	
    	for(eq='a';eq<='m';eq++)if(c2[eq-'a'])
    	for(mul='a';mul<='m';mul++)if(c1[mul-'a'])
    	for(add='a';add<='m';add++)if(c1[add-'a'])
    	if(eq!=mul&&add!=mul&&eq!=add)
    	if(!near[eq][mul]&&!near[eq][add]&&!near[mul][add])
    	{   
    		rep(i,0,12)w[i]=inf;w[eq-'a']=-1;w[add-'a']=-2;w[mul-'a']=-3;
    		
    		if(!predfs())continue;
    		
    		go(1,1,(1<<10)-1);
    	}
    	
    	
    	print();
    	
        return 0;
    }
    

      

  • 相关阅读:
    K8S 强制删除卡在Terminating状态的namespaces 记录
    docke 搭建 SVN服务器
    mysql-5.6--gtid主从配置
    keeplived + haproxy 高可用网络代理-安装配置 centos-7.6
    elasticsearch磁盘定时清理--转载
    HTTPS证书自动生成--certbot
    haproxy2.0-编译安装-centos7.6
    mongodb-定时按日期备份到json文件
    linux日志切割工具 logrotate
    mongodb--arbiter-集群安装
  • 原文地址:https://www.cnblogs.com/oldmanren/p/3808583.html
Copyright © 2011-2022 走看看