求最低价格

超能饮料 (关键字: chemical)文明盛世旗下的化工产品实验室一直在研究如何配制能够提高工程师生产效率、保持他们头脑清醒的新型兴奋剂。
研究已经分离了一系列化合物,当它们和糖水混合在一起就成为了下一代超能饮料的活性成分。

这些化合物成分类似:任何一种化合物都可经由某一化学反应,成为其它任意一种化合物。实际进行化学反应的成本很低,但使反应发生的设备和催化剂成本相当高昂。
把某一化合物转换为另一化合物时所使用的设备,也都必须单独定制。每件设备都会产生购置费用,并且需要投入某种化合物才能产出另外一种化合物。
文明盛世实验室必须配备足够设备,确保无论市场上能买到哪些化合物,都能产出整个系列的化合物。

编写仅带一个命令行参数的程序。该参数必须是一个包括输入数据的文件名。此程序应该输出最便宜的方案到标准输出,
使文明盛世公司能够利用源化合物或多个化合物生产其饮料(输出详情请参见下文)。我们假设设备目录中提到的所有化学品都是配制饮品的必要原料。
我们不保证所有的化学反应都能一步到位,不过我们保证任何一种化合物都能经由反应,转变为其它任意一种化合物。
参与者提交的谜题结果和程序方案都必须遵循下面的输入、输出规范,否则将会被视为不合格。参与者提交的程序将会在几个数据不同的设备目录上测试。
此外,参与者提交的程序运行速度必须很快,能在数分钟内给出正确方案。


输入规范
输入文件中需要包含可用设备列表。文件的每一行都代表一个特定的设备型号。每一行的格式如下:
<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;
}


原创转载请注明出处


原文地址:https://www.cnblogs.com/byfei/p/6389851.html