一、题目
二、解法
都很小,可以考虑状压,设 为完成目标数组的前 个,需要用已有数组的状态为 ,状态数本来就不大,所以直接记忆化搜索即可。
复杂度我觉得应该是枚举子集的子集,所以是 ,当然这只是上界,实际应该会快很多(搜索处剪枝)
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iostream>
using namespace std;
const int M = 20;
string s[]={" ","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"};
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,a[M],b[M],f[M][1<<18];
string t;vector<int> v;
int work(string x)
{
for(int i=1;i<=100;i++)
if(s[i]==x) return i;
}
void print()
{
int sum=0,j=0;
for(int i=0;i<v.size();i++)
{
sum+=v[i];
cout<<s[v[i]];
if(sum==b[j])
{
printf("->");
cout<<s[b[j++]];
puts("");sum=0;
}
else printf("+");
}
exit(0);
}
void dfs(int x,int sum,int s)
{
if(sum==b[x])
{
if(x==m)
{
puts("YES");
print();
}
else dfs(x+1,0,s);
return ;
}
if(sum>b[x]) return ;
if(f[x][s]) return ;
for(int i=0;i<n;i++)
{
if(s&(1<<i)) continue;
v.push_back(a[i]);
dfs(x,sum+a[i],s|(1<<i));
v.pop_back();
}
f[x][s]=1;
}
signed main()
{
n=read();m=read();
for(int i=0;i<n;i++)
{
cin>>t;
a[i]=work(t);
}
for(int i=0;i<m;i++)
{
cin>>t;
b[i]=work(t);
}
dfs(0,0,0);
puts("NO");
}