PAT(甲级)2020年冬季考试7-4 Chemical Equation (30分)

43 篇文章 0 订阅
28 篇文章 0 订阅

7-4Chemical Equation(30分)

A chemical equation is the symbolic representation of a chemical reaction in the form of symbols and formulae, wherein the reactant entities are given on the left-hand side and the product entities on the right-hand side. For example, CH​4​​ +2O​2​​ =CO​2​​ +2H​2​​ O means that the reactants in this chemical reaction are methane and oxygen: CH​4​​ and O​2​​ , and the products of this reaction are carbon dioxide and water: CO​2​​ and H​2​​ O.

Given a set of reactants and products, you are supposed to tell that in which way we can obtain these products, provided that each reactant can be used only once. For the sake of simplicity, we will consider all the entities on the right-hand side of the equation as one single product.

Input Specification:

Each input file contains one test case. For each case, the first line gives an integer N (2≤N≤20), followed by N distinct indices of reactants. The second line gives an integer M (1≤M≤10), followed by M distinct indices of products. The index of an entity is a 2-digit number.

Then a positive integer K (≤50) is given, followed by K lines of equations, in the format:

reactant_1 + reactant_2 + … + reactant_n -> product
where all the reactants are distinct and are in increasing order of their indices.

Note: It is guaranteed that

one set of reactants will not produce two or more different products, i.e. situation like 01 + 02 -> 03 and 01 + 02 -> 04 is impossible;
a reactant cannot be its product unless it is the only one on the left-hand side, i.e. 01 -> 01 is always true (no matter the equation is given or not), but 01 + 02 -> 01 is impossible; and
there are never more than 5 different ways of obtaining a product given in the equations list.

Output Specification:

For each case, print the equations that use the given reactants to obtain all the given products. Note that each reactant can be used only once.

Each equation occupies a line, in the same format as we see in the inputs. The equations must be print in the same order as the products given in the input. For each product in order, if the solution is not unique, always print the one with the smallest sequence of reactants – A sequence { a​1​​ ,⋯,a​m​​ } is said to be smaller than another sequence { b​1​​ ,⋯,b​n​​ } if there exists 1≤i≤min(m,n) so that a​j​​ =b​j​​ for all j<i, and a​i​​ <b​i​​ .

It is guaranteed that at least one solution exists.

Sample Input:

8 09 05 03 04 02 01 16 10
3 08 03 04
6
03 + 09 -> 08
02 + 08 -> 04
02 + 04 -> 03
01 + 05 -> 03
01 + 09 + 16 -> 03
02 + 03 + 05 -> 08

Sample Output:

02 + 03 + 05 -> 08
01 + 09 + 16 -> 03
04 -> 04

满分,最后一个测试用例293ms过了。槽点有点多。先介绍代码中的数据含义,node用来存储可能的(k + m)个化学式, node中的child用来存储对应化学式中的反应物,bitValue用来存储生成式中反应物的比特值总和(我在输入的时候用bits来映射每一个反应物为一个二进制下标便于计算总的化学式值,反应物值越大,二进制下标越小,对应二进制值越小)。temppath用来存储dfs过程中可能的解,每次都和最终解ans的MaxValue比较大小,如果比MaxValue大就把temppath赋值给ans,final1记录生成物是否被选取,final2记录反应物是否被选取,product记录生成物, reactant记录反应物(反应物在输入后排序是为了映射二进制下标), mm是映射输入的生成物的下标顺序便于最后结果输出, bit就是用来映射反应物的二进制下标的, dfs函数第一个参数是化学式的node下标, 第二个是vector中反应式个数(这个好像没什么用),value就是temppath中的化学式bitValue总和。在遍历前先按bitValue大小给node排个序然后就正常bfs就行。cmp函数用于最后结果按生成物顺序输出,cmp1函数用于排序node。

我写的不是优解,逻辑上也不知道有没有问题,只是靠遍历再加一点点剪枝,优解可以参考别的dalao的代码,他们的时间复杂度都是很小的,我的解题过程仅供参考。

#include<bits/stdc++.h>
using namespace std;
struct Node {
	int data, bitValue = 0;
	vector<int> child;
};
vector<Node> node, ans, temppath;
int n, m, k, MaxValue = 0;
bool visit[100] = {false};
unordered_map<int, bool> final1, final2;
vector<int> product, reactant;
unordered_map<int, int> mm, bits;
bool cmp(Node a, Node b) {
	return mm[a.data] < mm[b.data];
}
bool cmp1(Node a, Node b) {
	return a.bitValue > b.bitValue;
}
void dfs(int root, int num, int value) {
	if (num > m || root > m + k) return ;
	if (num == m) {
		if (value < MaxValue) return;
		if (ans.size() == 0) {
			ans = temppath;
			MaxValue = value;
			return;
		} else {
			if (value > MaxValue) {
				ans = temppath;
				MaxValue = value;
			}
			return ;
		}
	}
	if (final1[node[root].data]) {
		int flag = 1;
		for (int j = 0; j < node[root].child.size(); j++) {
			if (!final2[node[root].child[j]]) {
				flag = 0;
				break;
			}
		}
		if (flag) {
			for (int j = 0; j < node[root].child.size(); j++) {
				final2[node[root].child[j]] = false;
			}
			final1[node[root].data] = false;
			temppath.push_back(node[root]);
			dfs(root + 1, num + 1, value + node[root].bitValue);
			temppath.pop_back();
			final1[node[root].data] = true;
			for (int j = 0; j < node[root].child.size(); j++) {
				final2[node[root].child[j]] = true;
			}
		}
	}
	dfs(root + 1, num, value);
}
int main() {
	scanf("%d", &n);
	reactant.resize(n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &reactant[i]);
	}
	sort(reactant.begin(), reactant.end());
	for (int i = 0; i < n; i++) {
		final2[reactant[i]] = true;
		bits[reactant[i]] = n - 1 - i;
	}
	scanf("%d", &m);
	product.resize(m);
	for (int i = 0; i < m; i++) {
		scanf("%d", &product[i]);
		final1[product[i]] = true;
		mm[product[i]] = i;
	}
	scanf("%d", &k);
	node.resize(k + m);
	for (int i = k; i < m + k; i++) {
		vector<int> temp;
		temp.push_back(product[i - k]);
		node[i].data = product[i - k];
		node[i].child = temp;
	}
	string s;
	getchar();
	for (int i = 0; i < k; i++) {
		getline(cin, s);
		vector<int> temps;
		int id, datas;
		for (int j = 0; j < s.size(); j += 5) {
			if (s[j] == ' ') {
				id = stoi(s.substr(j + 1, 2));
				node[i].data = id;
				node[i].child = temps;
			} else {
				datas = stoi(s.substr(j, 2));
				temps.push_back(datas);
				node[i].bitValue += pow(2, bits[datas]);
			}
		}
	}
	sort(node.begin(), node.end(), cmp1);
	dfs(0, 0, 0);
	sort(ans.begin(), ans.end(), cmp);
	for (int i = 0; i < ans.size(); i++) {
		for (int j = 0; j < ans[i].child.size(); j++) {
			if (j != 0) printf(" + ");
			printf("%02d", ans[i].child[j]);
		}
		printf(" -> %02d\n", ans[i].data);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值