【搜索】核反应

核反应

描述

       现在我们有一堆核反应的方程式,但是遗憾的是他们的生成物部分的信息遗失了。好在我们通过以往的资料知道了总共消耗掉的反应物信息。你能根据核反应的原子序数守恒,确定这些信息是否属实?

输入

输入数据可能包含若干组数据。

每组数据由包含两个数N,M的一行开始,NM分别表示消耗掉的反应物个数和生成物个数。

接下来有两行,第一行有N个数,第二行有M个数,分别表示每个反应物和生成物。

输出

对于每组数据如果信息属实输出”YES”,否则输出”NO”

输入样例

10 3

Mn Co Li Mg C P F Zn Sc K

Sn Pt Y

2 1

H H

He

2 2

Bk Fm

Cf Es

输出样例

YES

YES

NO

数据规模

所有数据,1<=N,M<=17

可能用到的元素表:

"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"

第一组样例的解释:

Mn+C+K->Sn

Co+Zn+Sc->Pt

Li+Mg+P+F->Y

 

类似于小木棍。

剪枝比较多。

 

#include <iostream>
#include <algorithm>
#include <map>
#include <cstdio>
#include <string>
std::map<std::string,long> name;

char element[200][10] = {"","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"};

long A[20];
long B[20];

char tmp[10];

bool used[20];
bool flag = false;

long n=1;long m;

void dfs(long u,long l,long r)
{
 	if (r > m)
	{
		flag = true;
		return;
	}
	if (u > n)
		return;
	
	if (!used[u])
	{
		if (l + A[u] == B[r])
		{
			used[u] = true;
			dfs(1,0,r+1);
			if (flag)
				return;
			used[u] = false;
			return;		
		}
		if (l + A[u] < B[r])
		{
			used[u] = true;
			dfs(u+1,l+A[u],r);
			if (flag)
				return;
			used[u] = false;
		}
		if (l + A[u] > B[r])
		{
			return;
		}	
	}
	dfs(u+1,l,r);
}

int main()
{
	freopen("nuclear.in","r",stdin);
	freopen("nuclear.out","w",stdout);
	
	for (long i=1;i<sizeof(element)/sizeof(element[1])+1;i++)
	{
		name[element[i]] = i;
	}	
	
	while (scanf("%ld%ld",&n,&m)==2)
	{	
		for (long i=1;i<n+1;i++)
			used[i] = false;
		if (n < m)
		{
			printf("NO\n");
			continue;	
		}
		long l = 0;	
		A[0] = B[0] = 0;
		for (long i=1;i<n+1;i++)
		{
			scanf("%s",tmp);
			long tmp2 = name[tmp];
			l += tmp2;
			A[++A[0]] = tmp2;
		}
		long r = 0;
		for (long i=1;i<m+1;i++)
		{
			scanf("%s",tmp);
			long tmp2 = name[tmp];
			r += tmp2;
			B[++B[0]] = tmp2;
		}
		if (l - r)
		{
			printf("NO\n");
			continue;
		}
		std::sort(A+1,A+1+A[0]);
		std::sort(B+1,B+1+B[0]);
		if (B[1] < A[1] || B[B[0]] < A[A[0]])
		{
			printf("NO\n");
			continue;
		}
		
		flag = false;
		dfs(1,0,1);
		if (flag)
			printf("YES\n");
		else
			printf("NO\n");
	}
	
	return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值