BZOJ2570:算符破译题解
来源:互联网 发布:windows 用户鉴别信息 编辑:程序博客网 时间:2024/05/29 11:02
转载自Array98大大的博客
【题目描述】 考古学发现,几千年前古梅文明时期的数学非常的发达,他们懂得多位数的加法和乘法,其表达式和运算规则等都与现在通常所用的方式完全相同(如整数是十进制,左边是高位,最高位不能为零;表达式为中缀运算,先乘后加等),唯一的区别是其符号的写法与现在不同。有充分的证据表明,古梅文明的数学文字一共有13个符号,与 0,1,2,3,4,5,6,7,8,9,+,*,= 这13个数字和符号(称为现代算符)一一对应。为了便于标记,我们用13个小写英文字母a,b,…m代替这些符号(称为古梅算符)。但是,还没有人知道这些古梅算符和现代算符之间的具体对应关系。 在一个石壁上,考古学家发现了一组用古梅算符表示的等式,根据推断,每行有且仅有一个等号,等号左右两边为运算表达式(只含有数字和符号),并且等号两边的计算结果相等。 假设这组等式是成立的,请编程序破译古梅算符和现代算符之间的对应关系。【输入格式】 输入文件的第一行为等式的个数N(1<=N<=1000),以下N行每行为一个等式。 每个等式的长度为5个字符到11个字符。【输出格式】 如果不存在对应关系能够满足这组等式,输出“noway”和一个换行/回车符。 如果有对应关系能够满足这组等式,输出所有能够确定的古梅算符和现代算符的对应关系。每一行有两个字符,其中第一个字符是古梅算符,第二个字符是对应的现代算符。输出按照字典顺序排序。【样例输入】 2 abcdec cdefe【样例输出】 a6 b* d= f+【样例说明】 在上例中,可能对应的现代表达式为{6*2=12,2=1+1},{6*4=24,4=2+2},{6*8=48,8=4+4}。可见,能够确定的对应关系只有a对应6,b对应*,d对应=,f对应+,应该输出;而{c,e}虽然能够找到对应的现代算符使得等式成立,但没有唯一的对应关系,不能输出。其他古梅算符{g,h…m}完全不能确定,也不能输出。【分析】 相比消棋子我觉得还是这道题酸爽一点……毕竟不是单纯的模拟还要敲搜索疯狂的剪枝…………总之我讨厌写搜索,最让人痛恨的是调试搜索TAT 没有充足心里准备不要敲这道题= =反正终归是水过了嘛……下面来讲讲怎么做的。 首先,裸的搜索要敲对吧(PS:爆搜连样例都过不去调试毛线啊……) 这里无视Std各种各样的优化(标程一共敲了600行)然后编写是有一点要注意我们可以优先确定三个操作符的对应关系(体现在代码中的三个for循环,这样搜索就只需要搜数字)第一个优化:搜索时位运算压位,方便编写,加快速度,这个看代码应该都能理解。 第二个优化:其实算不上优化,就是我开始比较蠢……没写位运算,然后就是说把判断放到了搜索完之后……显而易见 O(N!) 连样例都过不了。 第三个优化:确定了运算符之后我们就可以大致确定出等号两边的数的位数,也就是大概的范围,这样可以直接跳过大量不可能的情况。最重要的优化。(对应代码中的Pre_Dfs)
/************************************************************** Problem: 2570 User: Array98 Language: C++ Result: Accepted Time:136 ms Memory:1060 kb****************************************************************/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int INF=int(1e9);const int MaxN=1010;int T;char a[MaxN][15]; int len[MaxN],lg2[(1<<10)+10];int w[15],Ans[15],st[15],cnt[15][MaxN];bool c1[15],c2[15],mark[15],Map[150][1150];char Equ,Mul,Add;bool Solved;inline int Id(char x) { return x-'a'; }int calc(){ int i,sum=0; for(;mark[st[0]-1];st[0]--) st[st[0]-1]=st[st[0]-1]*st[st[0]]; for (int i=1; i<=st[0]; i++) sum+=st[i]; st[0]=0; return sum;}bool check(int d){ int Last=-1,L=-1,R=-1; st[0]=0; for (int i=1; i<=len[d]; i++) { int c=w[Id(a[d][i])]; if(c>=0) if(Last>=0)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)L=calc(); else mark[st[0]]=0; } Last=c; } R=calc(); return L==R;}void Dfs(int d,int Now,int S){ bool Flag=1; for (int i=0; i<=12; i++) if(!(Ans[i]==w[i] || Ans[i]==-200)){ Flag=0; break; } if(Flag) return; if(d>T) { Solved=1; for (int i=0; i<=12; i++) 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(Now>len[d]) { if(check(d)) Dfs(d+1,1,S); return; } int ch=Id(a[d][Now]); if(w[ch]==INF) { for(int S2=S; S2; S2-=S2&-S2) { int t=lg2[S2&-S2]; if(Now==1 && t==0 && w[Id(a[d][2])]>0)continue; w[ch]=t; Dfs(d,Now+1,S-(S2&-S2)); w[ch]=INF; } } else Dfs(d,Now+1,S); }}int M,lw[15],rw[15];void Get_Range(int &L, int &R){ L=R=0; for (;M;M--) L=max(L,lw[M]),R=max(rw[M],R)+(R>0); }bool Pre_Dfs(){ int Last,L_l,L_r,R_l,R_r; for (int d=1; d<=T; d++) { M=0;Last=-1; for (int i=1; i<=len[d]; i++) { int c=w[Id(a[d][i])]; if(c==INF) { if(Last<0) M++,lw[M]=rw[M]=0; lw[M]++,rw[M]++; } else { if(M==0)return 0; for(; mark[M-1]; M--) lw[M-1]+=lw[M]-1,rw[M-1]+=rw[M]; if(c==-3) mark[M]=1; else if(c==-2) mark[M]=0; else if(c==-1) Get_Range(L_l,L_r); } Last=c; } Get_Range(R_l,R_r); if(L_r<R_l || R_r<L_l) { return 0; } } return 1;}int main(){ scanf("%d",&T); for (int i=1; i<=T; i++) scanf("%s",a[i]+1),len[i]=strlen(a[i]+1); for (int i=0; i<=15; i++) lg2[1<<i]=i,Ans[i]=-100; memset(c1,1,sizeof(c1)); for(char i='a';i<='m';i++) for (int j=1; j<=T; j++) { bool Flag=1; for (int k=1; k<=len[j]; k++) { if(k<len[j]) Map[a[j][k]][a[j][k+1]]=Map[a[j][k+1]][a[j][k]]=1; if(a[j][k]==i) cnt[Id(i)][j]++; } if(cnt[Id(i)][j]!=1) Flag=0; if(a[j][1]==i || a[j][len[j]]==i){ c1[i-'a']=0; Flag=0; } c2[Id(i)]=Flag; } for(Equ='a'; Equ<='m'; Equ++) if(c2[Id(Equ)]) for(Mul='a'; Mul<='m'; Mul++) if(c1[Id(Mul)]) for(Add='a'; Add<='m'; Add++) if(c1[Id(Add)]) if(Equ!=Mul && Add!=Mul && Equ!=Add) if(!Map[Equ][Mul] && !Map[Equ][Add] && !Map[Mul][Add]) { for (int i=0; i<=12; i++) w[i]=INF; w[Id(Equ)]=-1; w[Id(Add)]=-2; w[Id(Mul)]=-3; if(!Pre_Dfs()) continue; Dfs(1,1,(1<<10)-1); } for (int i=0; i<=12; i++) 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('\n'); } if(!Solved) printf("noway\n"); return 0;}
我自己打了5h,打了6k+,
最后WA了,是在下输了
蒟蒻就是蒟蒻
0 0
- BZOJ2570:算符破译题解
- BZOJ2570: [NOI2000]算符破译
- 破译密码
- myeclipse2014破译
- 破译密码
- 破译密码
- 邮件破译
- 破译密码
- 破译邮件
- Webstorm破译
- 邮件乱码巧破译
- 请教破译MD5?
- 破译MD5的王小云
- POJ 3749 破译密码
- pku 3749 破译密码
- 字符易位破译
- 图灵奖和破译~~
- PKU--3749 破译密码
- 如何下载oracle客户端
- perl中写数组的最值
- JS格式化时间
- OSI七层模型 以及 TCP/IP模型
- 平衡二叉树建立(有问题烦请指正)
- BZOJ2570:算符破译题解
- html中的标签meta的简单的介绍
- 杭电OJ-1073_Online Judge
- Redis01初识
- C语言的标准化
- 网址记录
- [数据结构] Set的基本用法
- 主程序做死循环,导致计时功能失效
- PHP Socket通信编程