首页 > 代码库 > 油瓶分油问题

油瓶分油问题

油瓶分油问题举例描述:

          例如:有三个大小不一样的且没有刻度的油瓶,其容量分别为12升、8升、5升;三个油瓶的初始油量为:12升、0升、0升;可以随意用某一瓶的油去灌满一瓶油,也可以把某一瓶的油全部倒入其他可以装下的一瓶油中,要求最后能得到一瓶装有6升的油。

编程要求:

         用户分三行分别输入各个油瓶的容量和各个油瓶的初始油量,最后一行再输入要求得到的目标油量。要求程序能够判断能否得到目标油量,入能则输出每一次倒油的步骤,不能得到则输出“不能得到目标油量”。只需要输出一中可行的分配方案即可。

        例如用户输入:

        12    8     5 (油瓶容量)

         12   0     0 (油瓶初始容量)

         6           要求得到的油量:


程序可以输出的一种方案是:

12 0 0

4 8 0

4 3 5

9 3 0

9 0 3

1 8 3

1 6 5

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<iterator>
using namespace std;

/*
*油瓶分油问题
*/

vector<vector<int>> GetScheme(vector<int> & vols,vector<int> & stas,int des)
{
	vector<vector<int>> scheme;//解集
	scheme.push_back(stas);
	vector<int> is_full(vols.size(),0);
	vector<int> vec;
	for(int i = 0;i<vols.size();i++)
	{
		if(vols[i]==stas[i])
			is_full[i] = 1;
	}
	//开始寻找解决方案
	while (true)
	{
		
		int index_full = find(is_full.begin(),is_full.end(),1) - is_full.begin();
		if(index_full != is_full.size() )//如果找到有已满的油瓶先从满的油瓶开始分起可以避免走弯路
		{
			//让满油瓶从左往右找到第一个可以装油的油瓶开始分油
			int  i;
			for(i = 0;i<vols.size();i++) 
			{
				if(is_full[i]!=1) {
					vec = stas;
					int need = vols[i] - stas[i];
					//先判断分配后的方案是否重复
					if(need>stas[index_full])
					{
						vec[i] += vec[index_full];
						vec[index_full] = 0;
					}else
					{
						vec[i]+=need;
						vec[index_full] -= need ;
					}
					if(find(scheme.begin(),scheme.end(),vec)==scheme.end())//不重复
					{
						if(need>stas[index_full])
						{
							stas[i] += stas[index_full];
							stas[index_full] = 0;
						}else
						{
							stas[i]+=need;
							is_full[i] = 1;
							stas[index_full] -= need ;
						}
						is_full[index_full] = 0;
						//保存
						scheme.push_back(vec);
						if(find(vec.begin(),vec.end(),des)!=vec.end())//如果已经找到目标油量则结束函数
						{
							return scheme ;
						}
						break;
					}
				}
			}
			if(i<vols.size())//如果满油瓶可以分配成功则直接进行下一次分配不需要再接着进行未满油瓶的分配
			{
				continue;
			}
		}
		//当没有满油瓶或者满油瓶没有分配成功时进行未满油瓶分配方案
		int i;
		for(i = 0;i<vols.size();i++)
		{
			if(stas[i]>0&&is_full[i]!=1)
			{
			//从左往右查找可以装油的油瓶
				int j;
				for ( j = 0;j < vols.size(); j++)
				{
					if(is_full[j]!=1&&j!=i)
					{

					vec = stas;
					int need = vols[j] - stas[j];
					//先判断分配后的方案是否重复
					if(need>stas[i])
					{
						vec[j] += vec[i];
						vec[i] = 0;
					}else
					{
						vec[j]+=need;
						vec[i] -= need ;
					}
					if(find(scheme.begin(),scheme.end(),vec)==scheme.end())//不重复
					{
						if(need>stas[i])
						{
							stas[j] += stas[i];
							stas[i] = 0;
						}else
						{
							stas[j]+=need;
							is_full[j] = 1;
							stas[i] -= need ;
						}
						is_full[i] = 0;
						//保存
						scheme.push_back(vec);
						if(find(vec.begin(),vec.end(),des)!=vec.end())//如果已经找到目标油量则结束函数
						{
							return  scheme;
						}
						break;
					}
					
					
					}
				}
				if(j<vols.size())
				{
					break;
				}
			
			}
		}
		//如果所有的方案都没有分配成功则为出现重复输出“不可能分配出目标油量”
		if(i>=vols.size())
		{
			scheme.clear();
			scheme.resize(0);
			return scheme;
		}
	}
}

int main()
{
	vector<int> vlos;//油瓶的容量
	vector<int> stas;//油瓶当前油量
	//输入各个油瓶的容量
	copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(vlos));
	cin.clear();
	cin.sync();
	//输入当前各个油瓶的油量
	copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(stas));

	int de_state;//目标油量
	cin.clear();
	cin.sync();
	cin>>de_state;

	vector<vector<int>> revec =   GetScheme(vlos,stas,de_state);
	if(revec.size()==0)
	{
		cout<<"不可能分配出目标油量"<<endl;
	}
	else
	{
		for (int i = 0; i < revec.size(); i++)
       {
		   copy(revec[i].begin(),revec[i].end(),ostream_iterator<int>(cout," "));
		   cout<<endl;
       }
	}
	return 0;
}



油瓶分油问题