泊松分酒
题目描述
泊松是法国数学家、物理学家和力学家。他一生致力科学事业,成果颇多。有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布。
有一次闲暇时,他提出过一个有趣的问题,后称为:“泊松分酒”。在我国古代也提出过类似问题,遗憾的是没有进行彻底探索,其中流传较多是:“韩信走马分油”问题。
有 3 个容器,容量分别为 12 升,8 升,5 升。其中 12 升中装满油,另外两个空着。要求你只用 3 个容器操作,最后使得某个容器中正好有 6升油。
下面的列表是可能的操作状态记录:
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
1,8,3
1,6,5
每行 3个数据,分别表示 12,8,6 升容器中的油量
第一行表示初始状态,第二行表示把 12 升倒入8 升容器后的状态,第三行是 8 升倒入 5 升...
当然,同一个题目可能有多种不同的正确操作步骤。
输入
输入各个容器的容量,开始的状态,和要求的目标油量
输入保证只有三个容器
输入保证按照容器的容量大小按照降序给出
保证所有数据都不会超过100
输出
程序通过计算输出一种实现的步骤(不需要找到所有可能的方法)。如果没有可能实现,则输出不可能
。
输入输出样例
样例输入 #1
复制
12,8,5,12,0,0,6
样例输出 #1
复制
12,0,0
4,8,0
4,3,5
9,3,0
9,0,3
1,8,3
1,6,5
提示
如果对答案判定有异议,请联系编写此题数据的对应管理员
思路:
首先你要明白这道题的倒酒,它是如何倒的,即它是全部倒入,还是可以控制倒酒的量,其实这道题是应该全部倒入,直至将其装满为止,什么意思?
比如数据12,12,12,12,0,0,6,你是不是以为是将第一瓶倒一半给第三瓶就好了,可是题干没有说瓶子有刻度,你如何确保正好倒一半,按1个单位来倒酒呢
接下来耐心看代码就好了,切记不要嫌代码太长,仔细研究你会发现逻辑是很清晰的,只不过有点冗杂罢了
代码实现:
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
struct node
{
int x;
int y;
int z;
};
const int N=105;
bool vis[N][N][N];
int Max_Va;
int Max_Vb;
int Max_Vc;
int init_Va;
int init_Vb;
int init_Vc;
int target;
vector< vector<node >> ans;
void dfs(int a,int b,int c,vector<node> v)
{
if(a==target || b==target || c==target) //判断终止条件
{
ans.push_back(v);
return;
}
//可操作的倒酒方式一共六种 a->b,a->c,b->a,b->c,c->a,c->b
//case 1: a->b
if(b+a>=Max_Vb && !vis[a-Max_Vb+b][Max_Vb][c])//a可以将b倒满,a有剩余
{
//a倒入b后还有剩余 倒入了 Max_Vb-b,a中剩余 a-Max_Vb+b
vis[a-Max_Vb+b][Max_Vb][c]=true;
v.push_back({a-Max_Vb+b,Max_Vb,c});
dfs(a-Max_Vb+b,Max_Vb,c,v);
v.pop_back();
vis[a-Max_Vb+b][Max_Vb][c]=false;
}
else if(b+a<Max_Vb && !vis[0][b+a][c]) //a不可以将b倒满,就将a倒空了
{
vis[0][b+a][c]=true;
v.push_back({0,b+a,c});
dfs(0,b+a,c,v);
v.pop_back();
vis[0][b+a][c]=false;
}
//case 2: a->c
if(c+a>=Max_Vc && !vis[a-Max_Vc+c][b][Max_Vc])//a可以将c倒满有剩余
{
vis[a-Max_Vc+c][b][Max_Vc]=true;
v.push_back({a-Max_Vc+c,b,Max_Vc});
dfs(a-Max_Vc+c,b,Max_Vc,v);
v.pop_back();
vis[a-Max_Vc+c][b][Max_Vc]=false;
}
else if(c+a<Max_Vc && !vis[0][b][c+a])//a不可以将c倒满
{
vis[0][b][c+a]=true;
v.push_back({0,b,c+a});
dfs(0,b,c+a,v);
vis[0][b][c+a]=false;
}
//case 3: b->a
if(a+b>=Max_Va && !vis[Max_Va][b-Max_Va+a][c])
{
vis[Max_Va][b-Max_Va+a][c]=true;
v.push_back({Max_Va,b-Max_Va+a,c});
dfs(Max_Va,b-Max_Va+a,c,v);
v.pop_back();
vis[Max_Va][b-Max_Va+a][c]=false;
}
else if(a+b<Max_Va && !vis[a+b][0][c])//b不可以将a倒满
{
vis[a+b][0][c]=true;
v.push_back({a+b,0,c});
dfs(a+b,0,c,v);
v.pop_back();
vis[a+b][0][c]=false;
}
//case 4:b->c
if(c+b>=Max_Vc && !vis[a][b-Max_Vc+c][Max_Vc])
{
vis[a][b-Max_Vc+c][Max_Vc]=true;
v.push_back({a,b-Max_Vc+c,Max_Vc});
dfs(a,b-Max_Vc+c,Max_Vc,v);
v.pop_back();
vis[a][b-Max_Vc+c][Max_Vc]=false;
}
else if(c+b<Max_Vc && !vis[a][0][c+b])//b不可以将c倒满
{
vis[a][0][c+b]=true;
v.push_back({a,0,c+b});
dfs(a,0,c+b,v);
v.pop_back();
vis[a][0][c+b]=false;
}
//case 5: c->a
if(a+c>=Max_Va && !vis[Max_Va][b][c-Max_Va+a])
{
vis[Max_Va][b][c-Max_Va+a]=true;
v.push_back({Max_Va,b,c-Max_Va+a});
dfs(Max_Va,b,c-Max_Va+a,v);
v.pop_back();
vis[Max_Va][b][c-Max_Va+a]=false;
}
else if(a+c<Max_Va && !vis[a+c][b][0])//c不可以将a倒满
{
vis[a+c][b][0]=true;
v.push_back({a+c,b,0});
dfs(a+c,b,0,v);
v.pop_back();
vis[a+c][b][0]=false;
}
//case 6: c->b
if(b+c>=Max_Vb && !vis[a][Max_Vb][c-Max_Vb+b])
{
vis[a][Max_Vb][c-Max_Vb+b]=true;
v.push_back({a,Max_Vb,c-Max_Vb+b});
dfs(a,Max_Vb,c-Max_Vb+b,v);
v.pop_back();
vis[a][Max_Vb][c-Max_Vb+b]=false;
}
else if(b+c<Max_Vb && !vis[a][b+c][0])//c不可以将b倒满
{
vis[a][b+c][0]=true;
v.push_back({a,b+c,0});
dfs(a,b+c,0,v);
v.pop_back();
vis[a][b+c][0]=false;
}
return;
}
int main()
{
scanf("%d,%d,%d,%d,%d,%d,%d",&Max_Va,&Max_Vb,&Max_Vc,&init_Va,&init_Vb,&init_Vc,&target);
vector<node> Path;
Path.push_back({init_Va,init_Vb,init_Vc});
vis[init_Va][init_Vb][init_Vc]=true;
dfs(init_Va,init_Vb,init_Vc,Path);
if(!ans.empty())
{
vector<node> t=ans[0];
for(int i=0; i<t.size(); i++)
{
printf("%d,%d,%d\n",t[i].x,t[i].y,t[i].z);
}
}
else puts("不可能");
return 0;
}