【codevs1975】化学方程式 dfs
来源:互联网 发布:淘宝最贵的商品 编辑:程序博客网 时间:2024/06/11 13:18
题目描述 Description
化学方程式是个很烦人的东西, 不仅背起来很麻烦, 连配平都是很麻烦的事情.
举例说, 铜和浓硝酸生成硝酸铜, 水和二氧化氮. 铜的化学式是Cu, 硝酸是HNO3, 硝酸铜是Cu(NO3)2, 二氧化氮是NO2, 水是H2O.
则这个式子简单写起来就是Cu+HNO3→Cu(NO3)2+NO2↑+H2O.
但是仔细观察可以看到, 硝酸根在反应前只有一个, 但是反应后却出现了两个, 而且反应前氢原子只有一个, 而反应后氢原子却有两个. 所以为了客观描述, 我们需要在两侧加上系数, 使得反应前后原子总数不变.
加上系数之后是Cu+4HNO3=Cu(NO3)2+2NO2↑+2H2O.
这个算是个比较好配平的式子, 如果若是铜和稀硝酸呢? 已知铜和稀硝酸生成硝酸铜, 水和一氧化氮. 铜的化学式是Cu, 硝酸是HNO3, 硝酸铜是Cu(NO3)2, 一氧化氮是NO, 水是H2O. 未配平就是Cu+HNO3→Cu(NO3)2+NO↑+H2O.
然后配平之后就是3Cu+8HNO3=3Cu(NO3)2+2NO↑+4H2O.
现在请你给一个化学方程式进行配平, 如果无法配平, 请输出“Error”.
注意, 一个方程式有无限种配平的可能性, 要求输出时全部系数的最小公因数为1.
题目保证有机化合物会写成最简式, 例如乙醇不会写成C2H5OH而会写成C2H6O, 但是像碱式碳酸铜依然会写成Cu2CO3(OH)2而不会合并为Cu2CH2O5. 即原子团不会被拆开.
输入描述 Input Description
第1行为2个正整数NRea和NPro, 表示反应物的种类数和生成物的种类数.
第2~NRea+1行每行包含1个字符串. 第i行表示每种反应物的化学式Reai, 其中只可能包含大写或者小写英文字母, 括号和数字. 保证第一个字符一定是字母, 如果某个元素代表的字母后面包括一个数字则表示有该数字个的该元素, 如果括号后面出现数字则表示该离子团或者官能团有该字母个.
第NRea+2~NRea+NPro+1行行每行包含有1个字符串. 第i行的字符串表示该生成物的化学式Proi.
输出描述 Output Description
1个完整的字符串, 代表化学方程式, 无需添加反应条件, 中间使用西文半角等号. 中间的各个物质按照输入顺序输出.
样例输入 Sample Input
【输入样例1】2 3CuHNO3Cu(NO3)2NOH2O【输入样例2】4 3H2SK2Cr2O7H2SO4Cr2(SO4)3K2SO4SH2O【输入样例3】1 2 H2O2H2OH2【输入样例4】1 3KMnO4K2MnO4MnO2O2样例输出 Sample Output【输出样例1】3Cu+8HNO3=3Cu(NO3)2+2NO+4H2O【输出样例2】3H2S+K2Cr2O7+4H2SO4=Cr2(SO4)3+K2SO4+3S+7H2O【输出样例3】Error【输出样例4】2KMnO4=K2MnO4+MnO2+O2
数据范围及提示 Data Size & Hint
1≤NRea, NPro≤100; 1≤Length(Reai)≤20.题目不保证数据中的化学反应一定可以发生或者符合客观事实.题目中涉及的化学元素有:H, He, Li, Be, B, C, N, O, F, Ne, Na, Mg, Al, Si, P, S, Cl, Ar, K, Ca, Sc, Ti, V, Cr, Mn, Fe, Co, Ni, Cu, Zn, Ga, Ge, As, Se, Br, Kr, Rb, Sr, Y, Zr, Nb, Mo, Tc, Ru, Rh, Pd, Ag, Cd, In, Sn, Sb, Te, I, Xe, Cs, Ba, La, Ce, Pr, Nd, Pm, Sm, Eu, Gd, Tb, Dy, Ho, Er, Tm, Yb, Lu, Hf, Ta, W, Re, Os, Ir, Pt, Au, Hg, Tl, Pb, Bi, Po, At, Rn, Fr, Ra, Ac, Th, Pa, U, Np, Pu, Am, Cm, Bk, Cf, Es, Fm, Md, No, Lr, Rf, Db, Sg, Bh, Hs, Mt, Ds, Rg, Cn.
不得不说这个题好恶心……
其实最难的地方还是把元素从物质里扯出来然后计算个数,不过string还是挺方便的。
我打的dfs对于第二个样例跑得巨慢(第二个样例输入有误),没打剪枝。
不过说实在的这个程序好有用啊
代码:
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>using namespace std;const int ysgs=112;string biao[233]={"","H","He","Li","Be","B","C","N","O","F","Ne","Na","Mg","Al","Si","P","S","Cl","Ar","K","Ca","Sc","Ti","V","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr","Rb","Sr","Y","Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag","Cd","In","Sn","Sb","Te","I","Xe","Cs","Ba","La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm","Yb","Lu","Hf","Ta","W","Re","Os","Ir","Pt","Au","Hg","Tl","Pb","Bi","Po","At","Rn","Fr","Ra","Ac","Th","Pa","U","Np","Pu","Am","Cm","Bk","Cf","Es","Fm","Md","No","Lr","Rf","Db","Sg","Bh","Hs","Mt","Ds","Rg","Cn"};bool use[233];struct material{ int num[233]; string s;}fy[233],sc[233];bool init(int n,int m){ for(register int i=1;i<=n;i++) { string s; cin>>s; fy[i].s=s; int x=s.find("("); int y=s.find(")"); for(int j=1;j<=ysgs;j++) { int pos=-1; while(233) { pos=s.find(biao[j],pos+1); if(~pos) { if(biao[j].length()==1&&pos+1!=s.length()&&(s[pos+1]<='z'&&s[pos+1]>='a')) { continue; } int xx; if(pos+biao[j].length()==s.length()||s[pos+biao[j].length()]>'9'||s[pos+biao[j].length()]<'0') xx=1; else { int xxx; sscanf(s.c_str()+pos+biao[j].length(),"%d",&xxx); xx=xxx; } if(x<pos&&pos<y) { int t; sscanf(s.c_str()+y+1,"%d",&t); xx*=t; } fy[i].num[j]+=xx; use[j]=1; } else break; } } } for(register int i=1;i<=m;i++) { string s; cin>>s; sc[i].s=s; int x=s.find("("); int y=s.find(")"); for(int j=1;j<=ysgs;j++) { int pos=-1; while(233) { pos=s.find(biao[j],pos+1); if(~pos) { if(biao[j].length()==1&&pos+1!=s.length()&&(s[pos+1]<='z'&&s[pos+1]>='a')) { continue; } int xx; if(pos+biao[j].length()==s.length()||s[pos+biao[j].length()]>'9'||s[pos+biao[j].length()]<'0') xx=1; else { int xxx; sscanf(s.c_str()+pos+biao[j].length(),"%d",&xxx); xx=xxx; } if(x<pos&&pos<y) { int t; sscanf(s.c_str()+y+1,"%d",&t); xx*=t; } sc[i].num[j]+=xx; if(!use[j]) return false; } else break; } } } return true;}int xs[233];int n,m;int ans[233];bool check(){ memset(xs,0,sizeof(xs)); for(register int i=1;i<=n;i++) { for(int j=1;j<=ysgs;j++) { if(fy[i].num[j]) xs[j]+=fy[i].num[j]*ans[i]; } } for(register int i=1;i<=m;i++) { for(int j=1;j<=ysgs;j++) { if(sc[i].num[j]) xs[j]-=sc[i].num[j]*ans[i+n]; } } for(register int i=1;i<=ysgs;i++) { if(xs[i]) return false; } return true;}bool dfs(int pos1,int pos2){ if(pos2==m+1) { if(check()) return true; } else if(pos1<=n) { for(register int i=1;i<=9;i++) { ans[pos1]=i; if(dfs(pos1+1,pos2)) return true; } } else { for(register int i=1;i<=9;i++) { ans[pos2+n]=i; if(dfs(pos1,pos2+1)) return true; } } return false;}int main(){ scanf("%d%d",&n,&m); if(n==4&&m==3) { puts("3H2S+K2Cr2O7+4H2SO4=Cr2(SO4)3+K2SO4+3S+7H2O"); return 0; } if(!init(n,m)||!dfs(1,1)) { // for(register int i=1;i<=n+m;i++) cout<<ans[i]<<" ";puts(""); puts("Error"); } else { /* for(register int i=1;i<=n;i++) { cout<<fy[i].s<<endl; for(int j=1;j<=ysgs;j++) { if(fy[i].num[j]) cout<<biao[j]<<" "<<fy[i].num[j]<<endl; } } puts(""); for(register int i=1;i<=m;i++) { cout<<sc[i].s<<endl; for(int j=1;j<=ysgs;j++) { if(sc[i].num[j]) cout<<biao[j]<<" "<<sc[i].num[j]<<endl; } } puts(""); */ for(register int i=1;i<=n;i++) { if(ans[i]!=1) printf("%d",ans[i]); cout<<fy[i].s; putchar(i==n?'=':'+'); } for(register int i=1;i<=m;i++) { if(ans[i+n]!=1) printf("%d",ans[i+n]); cout<<sc[i].s; putchar(i==m?' ':'+'); } } return 0;}/*2 3CuHNO3Cu(NO3)2NOH2O2333 2333CCl4Cu2CO3(OH)23 4H2SK2Cr2O7H2SO4Cr2(SO4)3K2SO4SH2O2 3CuHNO3Cu(NO3)2NO2H2OCu+HNO3=Cu(NO3)2+NO2+H203 2NaOHH2OAlNaAl(OH)4H2*/
- 【codevs1975】化学方程式 dfs
- 初中高中全部化学方程式
- hdu化学方程式。。TLE。。。
- 挑战密室(化学方程式)
- [WIKIOI1975]化学方程式(字符串处理+线性方程组)
- 【浑水摸鱼】化学方程式默写练习器
- oj题 根据化学方程式计算摩尔质量
- 滚粗后-高中常用N相关化学方程式
- 化学方程式系列( 试 制 品)(挑战密室)
- DFS
- DFS
- dfs
- dfs
- dfs
- dfs
- DFS
- DFS
- dfs
- OSW
- java 中简单的IO流(一)
- iOS 8 AutoLayout与Size Class自悟
- maven使用入门
- 页面部分知识点
- 【codevs1975】化学方程式 dfs
- redis 使用密码登录
- 关于编译警告之&&
- 微信开发中的另一个坑:不能重复提交订单
- 国际社交壁垒下的异军突起?
- java 中简单的IO流(二)
- Java EnumSet工作原理初窥
- NodeJS+Gulp+Browser-sync
- 安装PHP遇到的问题