研究已经分离了一系列化合物,当它们和糖水混合在一起就成为了下一代超能饮料的活性成分。

这些化合物成分类似:任何一种化合物都可经由某一化学反应,成为其它任意一种化合物。实际进行化学反应的成本很低,但使反应发生的设备和催化剂成本相当高昂。

把某一化合物转换为另一化合物时所使用的设备,也都必须单独定制。每件设备都会产生购置费用,并且需要投入某种化合物才能产出另外一种化合物。

文明盛世实验室必须配备足够设备,确保无论市场上能买到哪些化合物,都能产出整个系列的化合物。

编写仅带一个命令行参数的程序。该参数必须是一个包括输入数据的文件名。此程序应该输出最便宜的方案到标准输出,

使文明盛世公司能够利用源化合物或多个化合物生产其饮料(输出详情请参见下文)。我们假设设备目录中提到的所有化学品都是配制饮品的必要原料。

我们不保证所有的化学反应都能一步到位,不过我们保证任何一种化合物都能经由反应,转变为其它任意一种化合物。

参与者提交的谜题结果和程序方案都必须遵循下面的输入、输出规范,否则将会被视为不合格。参与者提交的程序将会在几个数据不同的设备目录上测试。

此外,参与者提交的程序运行速度必须很快,能在数分钟内给出正确方案。

输入规范

输入文件中需要包含可用设备列表。文件的每一行都代表一个特定的设备型号。每一行的格式如下:

<machine name>  <orig compound>  <new compound>  <price>(分别对应的中文意思是设备名称、源化合物、新化合物、价格)

设备名称要以字母‘M’开头(不要带引号)后跟一个非零整数。设备的名称可以是‘M1’、‘M2’、‘M13’等。

化合物名称要以字母‘C’开头(不要带引号)后跟一个非零整数。化合物的名称可以是‘C4’、‘C6’、‘C24’等。

价格请用简单的非零整数,请勿使用逗号、句号或单位符号(我们假设所有价格的单位都是美元)。如:‘987334’、‘13948295’等。

请在输入文件的段落之间用空格或制表符隔开。最后一项的行尾可以加入空格(也可以不加)。要确保所提交的程序能够通过数据格式正确的输入文件的运行验证。

输入文件示例:

设备名称 源化合物 新化合物  价格

M1      C1      C2      277317

M2      C2      C1      26247

M3      C1      C3      478726

M4      C3      C1      930382

M5      C2      C3      370287

M6      C3      C2      112344

输出规范

请严格按照以下说明进行输出:参与者的程序必须首先输出购买所需设备的总价(请勿插入逗号、句号或其它任何符号),

这个总价请用简单整数表示,结尾另起一行。

然后参与者提交的程序需打印所购买的设备编号,以升序排列并省略标志字符’M’。设备编号之间必须用一个空格隔开。

程序应该在最后一个设备编号后另起一行,而不能再加入空格。

输出示例(每行末尾需另起一行)

设备的总价

617317

设备编号

2  3  6 

//============================================================================
// Name : chemical.cpp
// Author : byfei
// Version :
// Copyright : Your copyright notice
// Description : chemical in C++, Ansi-style
//============================================================================

#include <iostream>
#include <fstream>
#include <list>
#include <map>
#include <vector>
//#include <windows.h>
using namespace std;

typedef int Tint32;
typedef bool TBool;
/* 题目
M1 C1 C2 277317
M2 C2 C1 26247
M3 C1 C3 478726
M4 C3 C1 930382
M5 C2 C3 370287
M6 C3 C2 112344

输出
617317
2 3 6
*/

struct Data
{
Tint32 m_nM1;
Tint32 m_nPrice;
Data(Tint32 nM1,Tint32 nPrice):
m_nM1(nM1),m_nPrice(nPrice)
{
}
};

typedef list<Data> ListData;
typedef map<Tint32,ListData> MapList;
typedef map<Tint32,Tint32> MapInt;

MapList SrcList; //新化合物列表需要的源化合物列表
MapList DestList; //源化合物能生成的新化合物列表
MapInt PriceByM; //根据机器编号获得价格
MapInt MinList; //最小价格机器编号列表
vector <int>a; //机器编号列表
Tint32 minPrice = 0; //总最小价格

//根据设备编号删掉多余的设备
void DelNum(MapList &SrcList,MapList &DestList,Tint32 nM)
{
MapList::iterator itr = SrcList.begin();
for (itr;itr != SrcList.end();++itr)
{
ListData::iterator it = itr->second.begin();
for (;it != itr->second.end();++it)
{
if(nM == it->m_nM1)
{
itr->second.erase(it);
break;
}
}
}

MapList::iterator itor = DestList.begin();
for (itor;itor != DestList.end();++itor)
{
ListData::iterator it = itor->second.begin();
for (;it != itor->second.end();++it)
{
if(nM == it->m_nM1)
{
itor->second.erase(it);
return;
}
}
}
}

//获得这个设备所在容器的数量
Tint32 GetNum(MapList &DataList,Tint32 nM)
{
MapList::iterator itr = DataList.begin();
for (itr;itr != DataList.end();++itr)
{
ListData::iterator it = itr->second.begin();
for (;it != itr->second.end();++it)
{
if(nM == it->m_nM1)
{
return itr->second.size();
}
}
}
return 0;
}

void myswap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}

//根据机器编号的全排列,排除法求最小值
void fuc(vector<int> &a,int n,int len)
{
if(n==1)
{
MapList TmpSrcList = SrcList;
MapList TmpDestList = DestList;
Tint32 nValue = 0;
MapInt TmpMinList;;
for(int i=0;i<len;++i)
{
Tint32 nM = a[i];
Tint32 nNumSrc = GetNum(TmpSrcList,nM);
Tint32 nNumDest = GetNum(TmpDestList,nM);
if(1< nNumSrc && 1 < nNumDest)
{
DelNum(TmpSrcList, TmpDestList,nM);
}
else
{
Tint32 nPrice = PriceByM[nM];
TmpMinList[nM] = nPrice;
nValue += nPrice;
}
if(0 != minPrice && minPrice < nValue)
{
break;
}
}
if(0 == minPrice || nValue <minPrice)
{
MinList = TmpMinList;
minPrice = nValue;
}
}
for(int i=0;i<n;++i)
{
myswap(a[i],a[n-1]);
fuc(a, n-1,len);
myswap(a[i],a[n-1]);
}
}

TBool LoadData(Tint32 nM,Tint32 nC1,Tint32 nC2,Tint32 nPrice)
{
PriceByM[nM] = nPrice;
a.push_back(nM);
//分为两类,源化合物能生成的新化合物,新化合物需要的原化合物
Tint32 nSrc = nC1; //源化合物
Tint32 nDest = nC2; //新化合物
MapList::iterator Srcitr = SrcList.find(nSrc);
MapList::iterator Destitr = DestList.find(nDest);
if(Srcitr == SrcList.end())
{
ListData TmpData;
TmpData.push_back(Data(nM,nPrice));
SrcList[nSrc] = TmpData;
}
else
{
Srcitr->second.push_back(Data(nM,nPrice));
}
if(Destitr == DestList.end())
{
ListData TmpData;
TmpData.push_back(Data(nM,nPrice));
DestList[nDest] = TmpData;
}
else
{
Destitr->second.push_back(Data(nM,nPrice));
}
return true;
}

int main()
{
//Tint32 nStar = GetTickCount();
char buffer[256];
char filename[256];
cout<<"Enter name of data file: ";
cin.getline(filename,256);
//char filename[256] = "d:\\chemical.txt";
ifstream myfile (filename);
if(!myfile){
cout << "Unable to open myfile";
exit(1);
}
Tint32 m,c1,c2,p;
while (! myfile.eof() )
{
myfile.getline (buffer,100);
sscanf(buffer,"%*c%d %*c%d %*c%d %d",&m,&c1,&c2,&p);
LoadData(m,c1,c2,p);
//cout<<m<<" "<<c1<<" "<<c2<<" "<<p<<endl;
}
Tint32 nLen = a.size();
fuc(a, nLen, nLen);
cout<<minPrice<<endl;
MapInt::iterator itr = MinList.begin();
for (itr;itr != MinList.end();++itr)
{
cout<<itr->first<<" ";
}
cout<<endl;
//cout<<GetTickCount()-nStar<<endl;
//system("pause");
return 0;
}

//============================================================================
// Name : chemical.cpp
// Author : byfei
// Version :
// Copyright : Your copyright notice
// Description : chemical in C++, Ansi-style
//============================================================================

#include <iostream>
#include <fstream>
#include <list>
#include <map>
#include <algorithm>
//#include <windows.h>
using namespace std;


/* 题目
M1 C1 C2 277317
M2 C2 C1 26247
M3 C1 C3 478726
M4 C3 C1 930382
M5 C2 C3 370287
M6 C3 C2 112344

输出
617317
2 3 6
*/

typedef int Tint32;
typedef bool TBool;
const int MAX = 100;
Tint32 nLen = 0;
struct Data
{
Tint32 m_nM1;
Tint32 m_nPrice;
Data(Tint32 nM1,Tint32 nPrice):
m_nM1(nM1),m_nPrice(nPrice)
{
}
};

typedef list<Data> ListData;
typedef map<Tint32,ListData> MapList;
typedef map<Tint32,Tint32> MapInt;

MapList SrcList; //新化合物列表需要的源化合物列表
MapList DestList; //源化合物能生成的新化合物列表
MapInt PriceByM; //根据机器编号获得价格
MapInt MinList; //最小价格机器编号列表
int a[MAX]; //机器编号列表
Tint32 minPrice = 0; //总最小价格

//根据设备编号删掉多余的设备
void DelNum(MapList &SrcList,MapList &DestList,Tint32 nM)
{
MapList::iterator itr = SrcList.begin();
for (itr;itr != SrcList.end();++itr)
{
ListData::iterator it = itr->second.begin();
for (;it != itr->second.end();++it)
{
if(nM == it->m_nM1)
{
itr->second.erase(it);
goto loop;
break;
}
}
}
loop:
MapList::iterator itor = DestList.begin();
for (itor;itor != DestList.end();++itor)
{
ListData::iterator it = itor->second.begin();
for (;it != itor->second.end();++it)
{
if(nM == it->m_nM1)
{
itor->second.erase(it);
return;
}
}
}
}

//获得这个设备所在容器的数量
Tint32 GetNum(MapList &DataList,Tint32 nM)
{
MapList::iterator itr = DataList.begin();
for (itr;itr != DataList.end();++itr)
{
ListData::iterator it = itr->second.begin();
for (;it != itr->second.end();++it)
{
if(nM == it->m_nM1)
{
return itr->second.size();
}
}
}
return 0;
}

void myswap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}

//根据机器编号的全排列,排除法求最小值
void permutation(int a[],int length)
{
sort(a,a+length);
do
{
MapList TmpSrcList = SrcList;
MapList TmpDestList = DestList;
Tint32 nValue = 0;
MapInt TmpMinList;;
for(int i=0;i<length;i++)
{
Tint32 nM = a[i];
Tint32 nNumSrc = GetNum(TmpSrcList,nM);
Tint32 nNumDest = GetNum(TmpDestList,nM);
if(1< nNumSrc && 1 < nNumDest)
{
DelNum(TmpSrcList, TmpDestList,nM);
}
else
{
Tint32 nPrice = PriceByM[nM];
TmpMinList[nM] = nPrice;
nValue += nPrice;
}
if(0 != minPrice && minPrice < nValue)
{
break;
}
}
if(0 == minPrice || nValue <minPrice)
{
MinList = TmpMinList;
minPrice = nValue;
}
}
while(next_permutation(a,a+length));
}

TBool LoadData(Tint32 nM,Tint32 nC1,Tint32 nC2,Tint32 nPrice)
{
PriceByM[nM] = nPrice;
a[nLen] = nM;
//分为两类,源化合物能生成的新化合物,新化合物需要的原化合物
Tint32 nSrc = nC1; //源化合物
Tint32 nDest = nC2; //新化合物
MapList::iterator Srcitr = SrcList.find(nSrc);
MapList::iterator Destitr = DestList.find(nDest);
if(Srcitr == SrcList.end())
{
ListData TmpData;
TmpData.push_back(Data(nM,nPrice));
SrcList[nSrc] = TmpData;
}
else
{
Srcitr->second.push_back(Data(nM,nPrice));
}
if(Destitr == DestList.end())
{
ListData TmpData;
TmpData.push_back(Data(nM,nPrice));
DestList[nDest] = TmpData;
}
else
{
Destitr->second.push_back(Data(nM,nPrice));
}
nLen++;
return true;
}

int main()
{
//Tint32 nStar = GetTickCount();
char buffer[256];
char filename[256];
cout<<"Enter name of data file: ";
cin.getline(filename,256);
//char filename[256] = "d:\\chemical.txt";
ifstream myfile (filename);
if(!myfile){
cout << "Unable to open myfile";
exit(1);
}
Tint32 m,c1,c2,p;
while (! myfile.eof() )
{
myfile.getline (buffer,100);
sscanf(buffer,"%*c%d %*c%d %*c%d %d",&m,&c1,&c2,&p);
LoadData(m,c1,c2,p);
//cout<<m<<" "<<c1<<" "<<c2<<" "<<p<<endl;
}
permutation(a, nLen);
cout<<minPrice<<endl;
MapInt::iterator itr = MinList.begin();
for (itr;itr != MinList.end();++itr)
{
cout<<itr->first<<" ";
}
cout<<endl;
//cout<<GetTickCount()-nStar<<endl;
//system("pause");
return 0;
}


//============================================================================
// Name : chemical.cpp
// Author : byfei
// Version :
// Copyright : Your copyright notice
// Description : chemical in C++, Ansi-style
//============================================================================

#include <iostream>
#include <fstream>
#include <list>
#include <map>
//#include <windows.h>
using namespace std;


/* 题目
M1 C1 C2 277317
M2 C2 C1 26247
M3 C1 C3 478726
M4 C3 C1 930382
M5 C2 C3 370287
M6 C3 C2 112344

输出
617317
2 3 6
*/

typedef int Tint32;
typedef bool TBool;
const int MAX = 100; //最大机器种类
Tint32 nLen = 0; //机器实际种类
struct Data
{
Tint32 m_nM1;
Tint32 m_nPrice;
Data(Tint32 nM1,Tint32 nPrice):
m_nM1(nM1),m_nPrice(nPrice)
{
}
};

typedef list<Data> ListData;
typedef map<Tint32,ListData> MapList;
typedef map<Tint32,Tint32> MapInt;

MapList SrcList; //新化合物列表需要的源化合物列表
MapList DestList; //源化合物能生成的新化合物列表
MapInt PriceByM; //根据机器编号获得价格
MapInt DelList; //被排除掉机器价格机器编号列表
Tint32 MaxPrice = 0; //所有机器总价格
Tint32 removePrice = 0; //排除掉的机器价格
int a[MAX]; //机器编号列表

//根据设备编号删掉多余的设备
void DelNum(MapList &SrcList,MapList &DestList,Tint32 nM)
{
MapList::iterator itr = SrcList.begin();
for (itr;itr != SrcList.end();++itr)
{
ListData::iterator it = itr->second.begin();
for (;it != itr->second.end();++it)
{
if(nM == it->m_nM1)
{
itr->second.erase(it);
goto loop;
}
}
}
loop:
MapList::iterator itor = DestList.begin();
for (itor;itor != DestList.end();++itor)
{
ListData::iterator it = itor->second.begin();
for (;it != itor->second.end();++it)
{
if(nM == it->m_nM1)
{
itor->second.erase(it);
return;
}
}
}
}

//获得这个设备所在容器的数量
Tint32 GetNum(MapList &DataList,Tint32 nM)
{
MapList::iterator itr = DataList.begin();
for (itr;itr != DataList.end();++itr)
{
ListData::iterator it = itr->second.begin();
for (;it != itr->second.end();++it)
{
if(nM == it->m_nM1)
{
return itr->second.size();
}
}
}
return 0;
}

void myswap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}

//根据机器编号的全排列,排除法求最小值
void combine(int a[], int n, int m)
{
m = m > n ? n : m;
int* order = new int[m+1];
for(int i=0; i<=m; i++)
order[i] = i-1;
int k = m;
bool flag = true;
while(order[0] == -1)
{
if(flag)
{
MapList TmpSrcList = SrcList;
MapList TmpDestList = DestList;
Tint32 nValue = 0;
MapInt TmpMinList;
for(int i=1; i<=m; i++)
{
Tint32 nM = a[order[i]]; //机器编号
Tint32 nNumSrc = GetNum(TmpSrcList,nM);
Tint32 nNumDest = GetNum(TmpDestList,nM);
if(1< nNumSrc && 1 < nNumDest)
{
DelNum(TmpSrcList, TmpDestList,nM);
Tint32 nPrice = PriceByM[nM];
TmpMinList[nM] = nPrice;
nValue += nPrice;
}
}
if(0 == removePrice || removePrice <nValue)
{
DelList = TmpMinList;
removePrice = nValue;
}
flag = false;
}
order[k]++;
if(order[k] == n)
{
order[k--] = 0;
continue;
}
if(k < m)
{
order[++k] = order[k-1];
continue;
}
if(k == m)
flag = true;
}
delete[] order;
}

TBool LoadData(Tint32 nM,Tint32 nC1,Tint32 nC2,Tint32 nPrice)
{
if(MAX < nM)
{
return false;
}
a[nLen] = nM;
PriceByM[nM] = nPrice;
//分为两类,源化合物能生成的新化合物,新化合物需要的原化合物
Tint32 nSrc = nC1; //源化合物
Tint32 nDest = nC2; //新化合物
MapList::iterator Srcitr = SrcList.find(nSrc);
MapList::iterator Destitr = DestList.find(nDest);
if(Srcitr == SrcList.end())
{
ListData TmpData;
TmpData.push_back(Data(nM,nPrice));
SrcList[nSrc] = TmpData;
}
else
{
Srcitr->second.push_back(Data(nM,nPrice));
}
if(Destitr == DestList.end())
{
ListData TmpData;
TmpData.push_back(Data(nM,nPrice));
DestList[nDest] = TmpData;
}
else
{
Destitr->second.push_back(Data(nM,nPrice));
}
nLen++;
MaxPrice+=nPrice;
return true;
}

int main()
{
//Tint32 nStar = GetTickCount();
char buffer[256];
char filename[256];
cout<<"Enter name of data file: ";
cin.getline(filename,256);
//char filename[256] = "d:\\chemical.txt";
ifstream myfile (filename);
if(!myfile)
{
cout << "Unable to open myfile";
exit(1);
}
Tint32 m,c1,c2,p;
while (! myfile.eof() )
{
myfile.getline (buffer,100);
sscanf(buffer,"%*c%d %*c%d %*c%d %d",&m,&c1,&c2,&p);
if(!LoadData(m,c1,c2,p))
{
cout << "M number is to big";
exit(1);
}
//cout<<m<<" "<<c1<<" "<<c2<<" "<<p<<endl;
}
myfile.close();
int N = nLen - SrcList.size(); //化合物种数
combine(a, nLen, N);
cout<<MaxPrice - removePrice<<endl;
for (int i=0;i < nLen;++i)
{
if(a[i]!=0)
{
if(DelList.find(a[i])==DelList.end())
cout<<a[i]<<" ";
}
}
cout<<endl;
//cout<<GetTickCount()-nStar<<endl;
//system("pause");
return 0;
}