穷举、贪心算法--泊松分酒(2)

博客围绕泊松分酒问题展开,初始酒量为 12 0 0,需用 12L、8L、5L 三个瓶子倒出 6L 酒。详细分析了倒酒的程序逻辑,对程序中各参数进行解释,还给出代码及相关解释,最后提到贪心算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泊松分酒问题:

初始酒量是 12 0 0,然后通过三个不同容量的瓶子(12L、8L、5L)倒出6L的酒出来

程序逻辑分析:

一下倒酒方式结果必须是可以结算出来的

当2为空的时候,1开始往2里面倒酒,出现两种情况,

一种:2满了,1还有剩余(2刚好满,1为0也考虑进来),这样的话就会出现1和2都有酒

另外一种:2没满,1没有剩余,这样的话1没有酒,2有酒

接上面,当2不为空,且3里面没满,出现两种情况

一种:3满了,2还有剩余(3刚好满2刚好为0也考虑进来),这样的话就会出现3和2都有酒

另外一种:3没满,2没有剩余,这样的话3有酒,2没有酒

接上面,当3满了之后,就向1里面添加酒,出现两种情况

一种:1满了,3还有剩余(1刚好满,3刚好为0也考虑进来),这样的话就会出现1和3都有酒

另外一种:1没满,3没有剩余,这的话就会出现1有酒,3没有酒的情况。

程序中参数解释:

b1 ,b2,b3指的是瓶子的容量;

bb1,bb2,bb3指的是瓶子内的酒量;

代码:

解释:有人会有疑问bb3==m是多余的,因为当前bb3的取值范围是bb3<=b3,这就是它的取值范围。但是b3的初始化值是会发送改变的,因为程序是会被改的。

解释:

if(bb2+bb3<=b3):if(bb2+bb3<=b3)说明bb2和bb3加起来的容量刚好或者还没倒满b3瓶子。这样的话bb2(b2)的里面当前是0,而bb3(b3)里面是他们两个的和。bb1(b1)不发送改变(因为我们没有动它啊);

else:说明bb2和bb3加起来要大于b3所能盛放的容量。这样的话,b3倒满之后,b2还有剩余,剩余的量bb2-(b3-bb3);

 解释:

if(bb3+bb1<=b1):同理说明倒完后瓶子b1没有满;

else:同理说明倒满了,b3瓶子还有剩余。

解释:

bb1>=b2:同理,说明b2倒满了,那么b2的当前酒量就是b2,b1的当前的酒量就是bb1-b2

else:同理,说明b2没有倒满,那么bb1里面的酒量为0,bb2里面的容量就是bb1的酒量。

将每次酒杯还存在的酒量结果打出来 

启动程序

运行结果

贪心算法:

import java.util.Scanner;

/**
 *
 * 取三个瓶子,分别放入3 5 8   量取的时候只需要取两个在它左右两边的即可,例如 取4 的话我们只需要3 6这两个瓶子,
 * 倒满大瓶子,然后倒满小瓶子里面,(判断大瓶子是否已经成立)然后倒掉小瓶子,在把剩下的倒入到小瓶子里面
 * 倒满大瓶子,然后倒满小瓶子里面,(判断大瓶子是否已经成立然后倒掉小瓶子,在把剩下的倒入到小瓶子里面
 */
public class Main1 {
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        int  X = in.nextInt();
        int Y = in.nextInt();
        int Z = in.nextInt();
        int CON = in.nextInt();
        int time=0;
        int[] arr={X,Y,Z};
        insertSort(arr);
        int[] pos = getPos(arr, CON);
        int min=pos[0];
        int max=pos[1];
        int x=0;
        int y=0;
        time=getMin(x,y,min,max,CON,time);
        System.out.print(time);
    }

    private static int[] getPos(int[] arr,int CON) {
        for (int i = 0; i < arr.length-1; i++) {
            if (arr[i]<CON && arr[i+1]>CON){
                return new int[] {arr[i],arr[i+1]};
            }
        }
        return new int[] {0,1};
    }

    public static void insertSort(int[] arr){
        if (arr.length<=1 || arr==null){
            return;
        }
        for (int i = 1; i <arr.length ; i++) {
            for (int j = i-1; j >=0 ; j--) {
                if (arr[j]>arr[j+1]){
                    swap(arr,j,j+1);
                }else {
                    break;
                }
            }
        }
    }
    public static void swap(int[] arr,int L,int R){
        int temp=arr[L];
        arr[L]=arr[R];
        arr[R]=arr[L];
    }

    private static int getMin(int x, int y,int min,int max, int continer,int time) {
        if (x==continer){
            return x;
        }else if (y==continer){
            return y;
        }
        time++;
       y=max;
       y=max-(min-x);
       time++;
       x=min;
       if (y==continer){
           return time;
       }
       time++;
       x=0;
        time++;
       x=y;
        time=getMin(x,y,min,max,continer,time);
       return time;
    }
}
/**
 *
 * 取三个瓶子,分别放入3 5 8   量取的时候只需要取两个在它左右两边的即可,例如 取4 的话我们只需要3 6这两个瓶子,
 * 倒满大瓶子,然后倒满小瓶子里面,(判断大瓶子是否已经成立)然后倒掉小瓶子,在把剩下的倒入到小瓶子里面
 * 倒满大瓶子,然后倒满小瓶子里面,(判断大瓶子是否已经成立然后倒掉小瓶子,在把剩下的倒入到小瓶子里面
 */

 

### 算法的 C++ 实现与解释 问题是经典的穷举法应用之一,主要通过模拟倒过程中的状态变化来解决问题。以下是基于引用的内容以及专业知识对该问题的详细解析。 #### 穷举法的核心思想 穷举法是一种依赖计算机强大计算能力的经典算法,适用于解决那些没有明显规律可循的问题[^2]。对于问题而言,可以通过枚举所有可能的状态转移路径找到最终解。 #### 问题描述 假设存在三个容器 A、B 和 C,别具有容量 `a`、`b` 和 `c` 升(其中 c 是目标容量),初始状态下只有 A 容器装满水,其余两个为空。目标是从 A 向 B 或 C 转移液体直到某个容器恰好含有目标体积 `c` 的液体为止。 #### 状态表示 为了便于编程实现,可以定义三元组 `(x, y)` 表示当前状态,其中: - `x`: 当前容器 B 中的水量; - `y`: 当前容器 C 中的水量。 初始状态为 `(0, 0)`,即两容器均为空;终止条件则为任意时刻满足其中一个容器内的水量等于目标值 `c`。 #### 关键操作析 根据题目设定,在每次操作过程中允许执行以下几种基本动作: 1. 将 A 的全部内容倒入 B 或者 C 直至后者满载或者前者清空; 2. 把 B 的部或整体转移到 C 反之亦然; 3. 清空任一非零存量的目标容器重新开始尝试填充其他对象直至达成预期结果为止。 这些逻辑可以用简单的数学关系表达出来并结合实际物理约束加以限制从而形成完整的解决方案框架如下所示: ```cpp #include <iostream> #include <queue> using namespace std; struct State { int a, b; }; bool visited[201][201]; // Assuming max capacity is less than or equal to 200 liters. void bfs(int capA, int capB, int target) { queue<State> q; State start = {capA, 0}; q.push(start); memset(visited, false, sizeof(visited)); visited[start.a][start.b] = true; while (!q.empty()) { State current = q.front(); q.pop(); if (current.a == target || current.b == target){ cout << "Solution found!" << endl; break; } vector<State> nextStates{ {0, current.b}, // Empty A. {current.a, 0}, // Empty B. {min(capA, current.a + current.b), ((current.a + current.b) > capA)?((current.a + current.b)-capA):0 },// Pour from B into A until A full. {(current.a + current.b >= capB)?(current.a-(capB-current.b)):0 , min(capB,(current.a+current.b))} //Pour from A into B untill B full. }; for(auto s :nextStates ){ if(!visited[s.a][s.b]){ visited[s.a][s.b]=true; q.push(s); } } } } int main(){ int A,B,C; cin>>A>>B>>C; bfs(A,B,C); } ``` 上述代码实现了利用广度优先搜索(BFS)方法寻找最短路径到达特定状态的功能[^3]^。这里采用了队列数据结构存储待访问节点,并借助二维布尔数组记录已探索过的组合防止重复处理相同情形造成死循环现象发生。 #### 结论 综上所述,通过对这一典型例子的学习我们可以发现即使面对看似复杂棘手的实际应用场景只要合理运用诸如穷举之类的通用技术手段同样能够有效应对各种挑战获得满意的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值