Codeforces 71E

dp[i] 表示状态i最多能合成前dp[i]所需要的元素

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

int n,k,s1,s2;
string s[100]={"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"};
string t;
int a[100],b[100],g[100][100];
int dp1[200000],dp2[200000],father[200000];
bool ok;

void read(int &x){
    cin>>t;
    for (int i=0;i<=99;i++)
        if (s[i]==t){
            x=i+1;
            return;
        }
}

void check(){
    for (int i=1;i<=(1<<n)-1;i++)
        for (int j=1;j<=n;j++)
            if (i&(1<<(j-1)))
                dp1[i]+=a[j];
    for (int i=1;i<=(1<<n)-1;i++){
        dp2[i]=-1;
        for (int j=i;j;j=(j-1)&i){
            if (dp2[i^j]!=-1 && b[dp2[i^j]+1]==dp1[j]){
                dp2[i]=dp2[i^j]+1;
                father[i]=i^j;
            }
        }
    }
    if (dp2[(1<<n)-1]==k) {
        ok=1;
        int x=(1<<n)-1;
        for (int i=k;i>=1;i--){
            for (int j=1;j<=n;j++)
                if ((1<<(j-1))&(x^father[x]))
                    g[i][++g[i][0]]=j;
            x=father[x];
        }
    }
}

int main(){
    cin>>n>>k;
    for (int i=1;i<=n;i++) {read(a[i]);s1+=a[i];}
    for (int i=1;i<=k;i++) {read(b[i]);s2+=b[i];}
    if (s1==s2) check();
    if (!ok) cout<<"NO\n";
    else {
        cout<<"YES\n";
        for (int i=1;i<=k;i++){
            cout<<s[a[g[i][1]]-1];
            for (int j=2;j<=g[i][0];j++)
                cout<<"+"<<s[a[g[i][j]]-1];
            cout<<"->"<<s[b[i]-1]<<"\n";
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值