YTU 1302 泊松分酒 搜索 dfs

泊松分酒

题目描述

泊松是法国数学家、物理学家和力学家。他一生致力科学事业,成果颇多。有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布。

有一次闲暇时,他提出过一个有趣的问题,后称为:“泊松分酒”。在我国古代也提出过类似问题,遗憾的是没有进行彻底探索,其中流传较多是:“韩信走马分油”问题。

有 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;
}


 

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值