我有以下列表:
动物食物 鲶鱼 狗猪肉 牛肉 我想以尽可能多的方式为动物分配食物,如:
每种不同的动物和食物组合都将存储在地图中。
(猫吃鱼, 狗吃猪肉)
(猫吃鱼, 狗吃牛肉)
(猫吃猪肉, 狗吃鱼)
(猫吃猪肉, 狗吃牛肉)
(猫吃牛肉, 狗吃鱼)
(猫吃牛肉, 狗吃猪肉)
最后,所有地图都会被放入一个集合中并返回。
我正在尝试使用递归函数,以下是我尝试的方法..但是我无法正确使用它,所以请帮助我做到。
提前致谢!!!
private static Set<Map<Animal, Food>> eats(List<Animal> animal, List<Food> food) {
Set<Map<Animal, Food>> returnSet = new HashSet<Map<Animal, Food>>();
Map<Animal, Food> map = new HashMap<Animal, Food>();
if (animal.size() == 0) {
return null; // There is no animal to feed
} else {
animalLoop: for (int i = 0; i < animal.size(); i++) {
foodLoop: for (int j = 0; j < food.size(); j++) {
map.put(animal.get(i), food.get(j));
food.remove(j);
break venueLoop;
}
}
animal.remove(i);
returnSet.add(map);
}
}
return returnSet.add(eats(animal, food));
}
答案 0 :(得分:1)
如果我们需要保留方法指纹并且不运行全局访问跟踪结构,这是一个可供参考的工作程序。
import java.util.*;
import java.util.stream.Collectors;
public class SFO_Recursive {
public enum Animal {
CAT, DOG ;
}
public enum Food {
FISH, BEEF, PORK ;
}
private static Set<Map<Animal, Food>> eats(List<Animal> animal, List<Food> food) {
Set<Map<Animal,Food>> fleet = new HashSet();
for (Animal a: animal){
for (Food f: food){
// Take a step with (a, f)
List<Food> food_left = food.stream().filter(x -> !x.equals(f)).collect(Collectors.toList());
List<Animal> animal_left = animal.stream().filter(x -> !x.equals(a)).collect(Collectors.toList());
if (animal_left.isEmpty() || food_left.isEmpty()){
// Terminal state
fleet.add(new HashMap<Animal, Food>(){{put(a,f);}});
}else {
eats(animal_left, food_left).stream().forEach(s -> {s.put(a, f); fleet.add(s); });
}
}
}
return fleet;
}
public static void main(String[] args){
SFO_Recursive.eats(
Arrays.asList(Animal.CAT, Animal.DOG),
Arrays.asList(Food.BEEF, Food.FISH, Food.PORK)
).stream().forEach(System.out::println);
}
}
结果是:
{CAT=BEEF, DOG=PORK}
{CAT=PORK, DOG=BEEF}
{CAT=BEEF, DOG=FISH}
{CAT=FISH, DOG=BEEF}
{CAT=FISH, DOG=PORK}
{CAT=PORK, DOG=FISH}
对于递归深度优先搜索,需要注意两件事:终端状态条件,以及如何将当前步骤应用于(未来)终端状态的部分结果。
如果我们必须保持方法指纹返回Set,输入为两个列表。终端条件是停止搜索的任一参数中的明显空列表。要将当前步骤应用于Set,我们可以循环所有地图,只需将新的Animal obj和新的Food obj的组合添加到每个地图,但依赖Set类来检查是否添加了唯一的Map。如果没有全局跟踪表,我们可以从动物和食物列表中删除消耗的元素,以将信息发送到下一个状态。
hashCode()的Java测试相等性。映射计算hashCode作为所有条目的总和,并且每个条目采用hashCode(k)^ hashCode(v)。默认情况下,每个枚举值都有一个唯一的hashCode。因此,可以直接添加Map元素。
答案 1 :(得分:0)
欢迎来到SO。这是让你入门的东西。这不是整个解决方案,只是一个起点。请参阅评论,并毫不犹豫地询问是否需要进一步澄清:
import java.util.ArrayList;
import java.util.List;
public class FoodAllocation{
private static List<String> foods;
public static void main(String[] args) {
//use <Animal> instead of String
List<String> animals = new ArrayList<>();
animals.add("Dog");animals.add("Cat");
//use Food> instead of String
foods = new ArrayList<>();
foods.add("Pork"); foods.add("Beef"); foods.add("Fish");
allocateFood(animals, null);
}
//recursively allocate
private static void allocateFood(List<String> animals, String eaten) {
//you can't change a list while iterating over it
//so make a of animals
List<String> animalsCopy = new ArrayList<>(animals);
//loop over animals
for (String animal : animals) {
//loop over food
for( String food : foods) {
if(food.equals(eaten)) {
continue;
}
//(add to a collection instead of printing )
System.out.println(animal +" eats " + food);
animalsCopy.remove(animal);
//food has been eaten
allocateFood(animalsCopy, food);
}
}
}
}