分酒问题(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 题目大意: 一个地图里面有三种元素,分别为"@",".","#",其中@为人的起始位置,"#"可以想象 ...
随机推荐
- escape()、encodeURI()、encodeURIComponent()区别详解(转)
JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,dec ...
- 详解AngularJS中的依赖注入
点击查看AngularJS系列目录 依赖注入 一般来说,一个对象只能通过三种方法来得到它的依赖项目: 我们可以在对象内部创建依赖项目 我们可以将依赖作为一个全局变量来进行查找或引用 我们可以将依赖传递 ...
- 【黑马18期Java毕业生】黑马程序员Java全套资料+视频+工具
Java学习路线图引言: 黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...
- JSP内置对象的实验报告,页面登陆设计
JSP内置对象的实验报告 一.实验目的: 本实验的目的是让学生掌握怎样在JSP中使用内置对象request.page.response等. 二.实验要求: 编写四个JSP 页面login.jsp.Re ...
- 从DDD开始说起
前言 从13年接触DDD之后开始做应用架构已经整整四个年头. 四年里关于DDD的感触良多,慢慢有了一些心得. 关于DDD的介绍已经有很多的文章和书籍,这里我推荐三本最重要的书籍. <领域驱动设计 ...
- 集群提交spark任务命令
>>spark-submit --class WordCount DataMining.jar /dept_ana/part-00000 /dept_ana/output/wordCou ...
- PHP,Mysql根据经纬度计算距离并排序
网上给出的计算公式是这样的: Lng1表示A点纬度和经度,Lat2 Lng2 表示B点纬度和经度 a = Lat1 – Lat2为两点纬度之差 b = Lng1 -Lng2 为两点经度之差 6378. ...
- asp.net mvc 自动化测试工具
好久不写文章了,一直忙在项目中. 前一阵发现公司一个项目,体积巨大.业务很复杂.基于历史原因,项目基于mvc 2迁移过来,视图大多还是aspx 作为视图承载. 控制器中的方法 更是一个比一个多. ...
- HelloWorld改编,仿bilibili手机端(一)——侧滑菜单界面布局
讲解目录: 1.要实现的效果图展示及详细分析HelloWorld项目的xml布局文件(基于navigation drawer activity) 2.简单修改menu及menu相关详解 ...
- MyBatis Generator配置示例
(一).MBG介绍 MyBatis Generator(MBG)是一个Mybatis的代码生成器,它可以用来生成可以访问(多个)表的基础对象.MBG解决了对数据库操作有最大影响的一些简单的CRUD(插 ...