震惊!原来这就是万恶之源!

  G题正确率跌破5%,ID为HDU8的用户刷屏提交记录四页,这一切的背后,到底是人性的灭亡,还是道德的沦丧…… 

  因为这道题没有出现在除去我们比赛的其他oj里(至少我没搜到),来看的估计都是熟人,我就放飞自我辽。
  这题我交了六十多次……太倔强了,我为自己鼓鼓掌
  A掉的时候贼高兴,所以就想搭个博客,所以G题就是万恶之源(严肃)
  WARNING:有用map,map名字叫aaa,可能引起阅读不适(但我就是不改这多有特点啊);只会举例论证,语言逻辑不太行

题目:化学方程式

描述
102班每天要写化学方程式,现在要想办法批改方程式。方程式中反应物的顺序可以不一样,中间可以有空格。不会出现沉淀和气体符号和反应条件。错误有系数不对(下标不对,如CO2为CO3也算系数不对。反应物或生成物中不会出现元素相同,系数不同的化学式,如:CO和CO2不会一起出现在反应物或生成物中),化学式错误,缺少反应物,两边元素不守恒。
输入
第一排输入N,M
第二排输入长度为N的字符串为正确方程式
第三排输入长度为M的字符串为要批改方程式
输出
正确输出RIGHT
错误第一排输出WRONG,第二排输出错误原因(只系数不对为1,其他错误和有两个以上错误为2)
输入样例 1
34 29
2Na O H + H2S O4 = Na 2 S O4+2H2O
H2S O4 +2NaO H =Na2 S O4+2H2O
输出样例 1
RIGHT
输入样例 2
34 25
2Na O H + H2S O4 = Na 2 SO4 +2H2O
H2S O4 +NaO H=2H2O +2 K Cl
输出样例 2
WRONG
2

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<map>
#include<string>
#include<vector>
#include<sstream>
#define INF 0xfffffff
using namespace std;
int n, m, k;
int a, b, c, d;
int sum, ans, num, cnt;
string s, sa, sb;
map<string, int>aaa;
int main() {
cin >> n >> m;
getchar();
cnt = 1;
aaa.clear();
string s1[100], s2[100];
for (int i = 0; i < 100; i++)
s1[i] = "", s2[i] = "";
while (1) {
s = getchar();
if (s == "\n") break;
else if (s != "+"&&s != "="&&s != " ") s1[cnt] += s;
else if (s == "+") cnt++;
else if (s == "=") a = cnt, cnt++;//a是存反应物和生成物的分隔
}
int tt = cnt;
for (int i = 1; i <= cnt; i++) {
sa = "";
aaa[s1[i]] = i;
for (int j = 0; j < s1[i].length(); j++)
if (s1[i][j] <= '0'||s1[i][j] >= '9')
sa += s1[i][j];//去数字
if (!aaa[sa]) aaa[sa] = ++tt;//系数去掉后也存一下
}
int cnt2 = 1;
int flag = 1;//flag设置为1是因为全对全错都比半对好考虑
sum = 0;
int p[100];
memset(p, 0, sizeof(p));
while (1) {
s = getchar();
if (s == "\n") break;
else if (s != "+"&&s != "="&&s != " ") s2[cnt2] += s;
else if (s == "+") cnt2++;
else if (s == "=") b = cnt2, cnt2++;
}//复读机
if (cnt2 != cnt) flag = 2;//一二式方程式里物质数目不同直接错
for (int i = 1; i <= cnt2; i++) {
sb = "";
if (flag == 2) break;
for (int j = 0; j < s2[i].length(); j++)
if (s2[i][j] <= '0'||s2[i][j] >= '9')
sb += s2[i][j];
if (aaa[s2[i]] && aaa[s2[i]] <= cnt && !p[aaa[s2[i]]])
sum++, p[aaa[s2[i]]] = 1;//包含系数物质的直接比较 和一式一样计数+标记
// aaa[s2[i]] <= cnt的存在必要:如一式是2HCl二式是HCl
// p[aaa[s2[i]]] = 1的存在必要:一式CO+CuO=Cu+CO2二式CO+CuO=Cu+CO
else if (!aaa[sb]) flag = 2;//去掉系数了还没有存过肯定是错的了
if (aaa[s2[i]] > a && aaa[s2[i]] <= cnt && i <= b) flag = 2;
//判断生成物和反应物有没有跑错位子
}
if (flag == 1 && sum == cnt) flag = 0;
if (!flag) cout << "RIGHT" << endl;
else cout << "WRONG" << endl;
if (flag) cout << flag << endl;
return 0;
}

  其实这题走了好多弯路,怪自己太瞎题目没看清(反思)
  删删改改,从五六十加加加到百来行再删删删到七十行(然后再加加加注释)
  这个解系数为1不能判断,不过讲道理化学方程式系数为1确实不写
  CO2和CO3只是系数错了能把化学老师气死(也把我气死了,所以一开始是开了vector的)
  比较常规而且又稳的解法应该是四个map+一个vector,顾老师好像就是这样不过他还分了单质啊什么的我也没细看= =反正我这个能A嘻嘻