分酒问题(DFS解法)
题目大概是这样:
已知有三个容量分别为3千克、5千克和8千克的并且是没有刻度的酒瓶,3千克和5千克的瓶子均装满了酒,而8千克的瓶子为空。现要求仅用这三个酒瓶将这些酒均分为两个4千克并分别装入5千克和8千克的瓶子中。
题解:
可以扩展为有n个瓶子,每个瓶子当前装了x1,x2,x3…xn的酒,每个瓶子的上限是y1,y2,…yn,目标状态是每个瓶子d1,d2,…dn,现在要从当前状态转换到目标状态
可以解读到,每个瓶子只有两种状态--要么盛满,要么空
所以当酒从x瓶子转移到y瓶的时候,只有可能是试图将酒全部到入y瓶中,这样会造成两种结果:
能盛得下-- x瓶空,y瓶的酒为原来的酒加上x瓶原来的酒。
盛不下-- x瓶的酒为原来的酒减去倒过去的那部分, y瓶满。
很显然,如果要求最短的步数,BFS是一个比较简单的办法,现在想输出所有的路径,所以考虑DFS
代码:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner; //已知有3个容量分别为3kg,5kg和8kg且没有刻度的酒瓶3kg和5kg的瓶子均装满了酒。而8kg的瓶子为空。
//现要求仅用这3个酒瓶将这些酒均分为两个4kg,并分别装入5kg和8kg的瓶子中。 public class DispensingProblem {
public static int N; //酒瓶的数量
public static Integer[] bottleMax; //每个酒瓶最多装多少酒
public static Integer[] bottleCurrent; //每个酒瓶现在装了多少酒
public static Integer[] bottleFinal; //标注每个酒瓶的最终状态
public static ArrayList<String> states; //标注每一种状态,防止重复(每一种状态是一个向量,我用整型数组表示)
public static ArrayList<String[]> paths; //标注每一条路径
public static int caseNum = 0; //标注是第几种方法
public static int minNum = 1000000; //标注最少需要的步数
public static void dfs(int n){
String testS = String.valueOf(bottleCurrent[0]);
for(int m =1;m<N;m++)
testS+=String.valueOf(bottleCurrent[m]);
boolean flag = true;
for(int k = 0;k<N;k++)
if(bottleCurrent[k]!=bottleFinal[k])
flag = false;
if(flag){
caseNum ++ ;
if(n <= minNum){
if(n<minNum){
paths.clear();
}
String[] tempS= new String[states.size()];
for(int ll = 0;ll<states.size();ll++)
tempS[ll] = states.get(ll);
paths.add(tempS);
minNum = n;
}
System.out.println("第"+caseNum+"种方法:");
for(int l=0;l<states.size();l++)
System.out.println(states.get(l));
System.out.println("总共需要移动"+n+"步");
System.out.println("------------------------------------");
return;
}
//找出当前可能的所有移动
//数据不大,不需要优化
//每个瓶子只能倒满或者倒空
//注意要标注每一种状态,防止状态重复
for(int i = 0 ; i < N;i++)
for(int j = 0; j < N ;j++){
if(i==j)
continue;
//从i瓶把所有酒倒入j瓶
int nI = bottleCurrent[i];
int nJ = bottleCurrent[j];
int temp = nI + nJ - bottleMax[j];
if(temp<=0){
//能全倒进去
bottleCurrent[i] = 0;
bottleCurrent[j] = nI + nJ;
String s = String.valueOf(bottleCurrent[0]);
for(int m =1;m<N;m++)
s+=String.valueOf(bottleCurrent[m]);
if(!states.contains(s)){
states.add(s);
dfs(n+1);
//回溯
states.remove(states.indexOf(s));
}
//回溯
bottleCurrent[i] = nI;
bottleCurrent[j] = nJ;
}
else{
//不能全倒进去
bottleCurrent[i] = temp;
bottleCurrent[j] = bottleMax[j];
String s = String.valueOf(bottleCurrent[0]);
for(int m =1;m<N;m++)
s+=String.valueOf(bottleCurrent[m]);
if(!states.contains(s)){
states.add(s);
dfs(n+1);
//回溯
states.remove(states.indexOf(s));
}
//回溯
bottleCurrent[i] = nI;
bottleCurrent[j] = nJ;
}
}
//找遍所有状态都不可行,则表明不能出现这种状态
//System.out.println("不可能存在这种状态!");
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("请输入瓶子个数");
N = sc.nextInt();
bottleMax = new Integer[N];
bottleCurrent = new Integer[N];
bottleFinal = new Integer[N];
states = new ArrayList<String>();
paths = new ArrayList<String[]>();
System.out.println("请输入每个瓶子的容量");
for(int i = 0 ;i < N; i ++){
bottleMax[i] = sc.nextInt();
}
System.out.println("请输入每个瓶子当前有多少酒");
for(int i = 0 ;i < N; i ++){
bottleCurrent[i] = sc.nextInt();
}
System.out.println("请输入最终希望每个瓶子有多少酒");
for(int i = 0 ;i < N; i ++){
bottleFinal[i] = sc.nextInt();
}
String s = String.valueOf(bottleCurrent[0]);
for(int i =1;i<N;i++)
s+=String.valueOf(bottleCurrent[i]);
states.add(s);
dfs(0);
System.out.println("******************************");
System.out.println("最少需要"+minNum+"步");
int index = 0;
for(int i = 0;i<paths.size();i++){
index++;
System.out.println("第"+index+"种最短方法:");
String[] temp = paths.get(i);
for(int j = 0;j<temp.length;j++)
System.out.println(temp[j]);
System.out.println("-----------------------------------");
}
System.out.println("******************************");
}
}
分酒问题(DFS解法)的更多相关文章
- 算法笔记_219:泊松分酒(Java)
目录 1 问题描述 2 解决方案 1 问题描述 泊松是法国数学家.物理学家和力学家.他一生致力科学事业,成果颇多.有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布. 有一次闲暇时,他 ...
- Java实现 泊松分酒
泊松是法国数学家.物理学家和力学家.他一生致力科学事业,成果颇多.有许多著名的公式定理以他的名字命名,比如概率论中著名的泊松分布. 有一次闲暇时,他提出过一个有趣的问题,后称为:"泊松分酒& ...
- UVALive 6450 Social Advertising DFS解法
题意:一些人有朋友关系,在某个人的社交网站上投放广告可以被所有该人的直接朋友看到,问最小投放多少个广告使给出的人都看到广告.(n<=20) 解法:看到n的范围可以想到用二进制数表示每个人被覆盖与 ...
- 分珠(dfs+并查集)
1140 分珠 时间限制:500MS 内存限制:65536K提交次数:24 通过次数:18 题型: 编程题 语言: G++;GCC Description 如下图所示,有若干珠子,每颗珠子重量不 ...
- PTA 1004 Counting Leaves (30)(30 分)(dfs或者bfs)
1004 Counting Leaves (30)(30 分) A family hierarchy is usually presented by a pedigree tree. Your job ...
- PAT 甲级 1018 Public Bike Management (30 分)(dijstra+dfs,dfs记录路径,做了两天)
1018 Public Bike Management (30 分) There is a public bike service in Hangzhou City which provides ...
- 蓝桥杯-分考场(dfs)
分考场 PREV-53 这题的解决方法使用dfs,因为数据很小,才100. 每次当前的人人是否可以和前面的组队,设置两个数组group和fri /*DFS求解:思路每次判断输入的人是否可以和前面的组队 ...
- hdu4982 Goffi and Squary Partition (DFS解法)
BestCoder Round #6 B http://acm.hdu.edu.cn/showproblem.php?pid=4982 Goffi and Squary Partition Time ...
- HDU 1312 Red and Black --- 入门搜索 DFS解法
HDU 1312 题目大意: 一个地图里面有三种元素,分别为"@",".","#",其中@为人的起始位置,"#"可以想象 ...
随机推荐
- hdu1556树状数组的区间更新单点查询
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- poj1067威佐夫博奕
取石子游戏 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 31490 Accepted: 10374 Descripti ...
- NOIP2017SummerTraining0712
个人感受:打了三个小时不到的第一题,然后也就没有多少时间去搞第二题了,特别是第二题还看到了期望这样的东西,这个难以理解,第三题的树分治,myx大佬说50分好拿,但是我觉得也挺难拿的. 单词检索 时间限 ...
- Python文件读写模式
r 打开只读文件,该文件必须存在. r+ 打开可读写的文件,该文件必须存在.可读,可写,可追加. w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失.若文件不存在则建立该文件. w+ 打 ...
- VB.NET 中 ComboBox 如何清除选项--- 使用Dataset 赋值 DataSource 的时候
如题: 在 使用Dataset 赋值 DataSource 的时候,网络上很多都是:ComboBox2.DataSource = Null 然并卵,很高兴告诉大家:Null 在VB.NET中是没用的: ...
- 演示 Calendar 的一般操作
package com.yixin.webbrower; /* * 演示 Calendar 的一般操作 */ import java.util.Date; import java.text.Simpl ...
- WPF中的imagesource 和内存图片的处理
[转载]ImageSource的使用心得 很多时候,我们会使用图片来装饰UI,比如作为控件背景等. 而这些图片可以分为两种形式,即存在于本地文件系统中的图片和存在于内存中的图片 对于这两种形式的图片, ...
- JS中的作用域以及全局变量的问题
一. JS中的作用域 1.全局变量:函数外声明的变量,称为全部变量 局部变量:函数内部使用var声明的变量,称为局部变量在JS中,只有函数作用域,没有块级作用域!!!也就是说,if/for等有{}的结 ...
- 【学习】原生js学习笔记1:添加class和使input为不可用
<input type="checkbox" id="new_check" onChange="noUse()" checked> ...
- 为选择屏幕的字段设置F4帮助
在没有参考 数据元素,域和搜索帮助的情况下,自定义F4 帮助 1,PARAMETERS: p_bukrs(4) TYPE C MATCHCODE OBJECT H_T001. 2,AT SELECTI ...