找到了这个谜题HERE ...我做了一个蛮力解决方案,我想知道你是如何解决它的......
Buzz,Woody,Rex和Hamm必须逃离Zurg(a)他们只需要越过 在他们自由之前的最后一座桥。但是,这座桥很脆弱,最多可以容纳 其中两个在同一时间。而且,要穿过桥,需要手电筒 避免陷阱和破损的部分。问题是我们的朋友只有一个手电筒 一个电池只能持续60分钟(这不是一个错字:六十个)。玩具需要 穿越桥梁的不同时间(向任一方向):
TOY TIME
Buzz 5 minutes
Woody 10 minutes
Rex 20 minutes
Hamm 25 minutes
由于桥上同时只有两个玩具,它们无法越过 一下子就连起来。因为他们需要手电筒过桥,每当两个人都有 过了桥,有人不得不回去把手电筒带到那些玩具上 另一边仍然要过桥。 现在的问题是:四个玩具能够以何种顺序及时过桥(那个 是在60分钟内从Zurg得救?
//(a) These are characters from the animation movie “Toy Story 2”.
这是我的解决方案:
public Form1()
{
InitializeComponent();
List<toy> toys = new List<toy>(){
new toy { name = "buzz", time = 5 } ,
new toy { name = "woody", time = 10 } ,
new toy { name = "rex", time = 20 } ,
new toy { name = "ham", time = 25 } ,
};
var posibles = Combinaciones(toys, 4).ToList(); //all permutations
List<Tuple<string, int>> solutions = new List<Tuple<string, int>>();
foreach (var pointA in posibles)
{
string order = "";
int flashlight = 60;
List<toy> pointB = new List<toy>();
do
{
var fastestInA = pointA.Take(2).ToList();
flashlight -= fastestInA.Max(t => t.time);
order += "go " + String.Join(",", fastestInA.Select(t => t.name)) + "\n";
fastestInA.ForEach(t => pointA.Remove(t));
pointB.AddRange(fastestInA);
if (pointB.Count < 4)
{
var fastestInB = pointB.Take(1).ToList();
flashlight -= fastestInB.Max(t => t.time);
order += "return " + String.Join(",", fastestInB.Select(t => t.name).ToArray()) + "\n";
fastestInB.ForEach(t => pointB.Remove(t));
pointA.AddRange(fastestInB);
}
} while (pointB.Count != 4);
solutions.Add(new Tuple<string, int>(order, flashlight));
}
var optimal = solutions.Where(s => s.Item2 == solutions.Max(t => t.Item2)).ToList();
optimal.ForEach(s => Console.Write("Order:\n" + s.Item1 + "TimeLeft:" + s.Item2 + "\n\n"));
}
public class toy
{
public int time { get; set; }
public string name { get; set; }
}
// this is to do permutations
public static List<List<toy>> Combinaciones(List<toy> list, int take)
{
List<List<toy>> combs = new List<List<toy>>();
foreach (var item in list)
{
var newlist = list.Where(i => !i.Equals(item)).ToList();
var returnlist = take <= 1 ? new List<List<toy>> { new List<toy>() } : Combinaciones(newlist, take - 1);
foreach (var l in returnlist)
{
l.Add(item);
}
combs.AddRange(returnlist);
}
return combs.ToList();
}
}
答案 0 :(得分:5)
使用LINQ的递归解决方案:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Zurg
{
class Program
{
static readonly Toy[] toys = new Toy[]{
new Toy("Buzz", 5),
new Toy("Woody", 10),
new Toy("Rex", 20),
new Toy("Ham", 25),
};
static readonly int totalTorch = 60;
static void Main()
{
Console.WriteLine(Go(new State(toys, new Toy[0], totalTorch, "")).Message);
}
static State Go(State original)
{
var final = (from first in original.Start
from second in original.Start
where first != second
let pair = new Toy[]
{
first,
second
}
let flashlight = original.Flashlight - pair.Max(t => t.Time)
select Return(new State(
original.Start.Except(pair),
original.Finish.Concat(pair),
flashlight,
original.Message + string.Format(
"Go {0}. {1} min remaining.\n",
string.Join(", ", pair.Select(t => t.Name)),
flashlight)))
).Aggregate((oldmax, cur) => cur.Flashlight > oldmax.Flashlight ? cur : oldmax);
return final;
}
static State Return(State original)
{
if (!original.Start.Any())
return original;
var final = (from toy in original.Finish
let flashlight = original.Flashlight - toy.Time
let toyColl = new Toy[] { toy }
select Go(new State(
original.Start.Concat(toyColl),
original.Finish.Except(toyColl),
flashlight,
original.Message + string.Format(
"Return {0}. {1} min remaining.\n",
toy.Name,
flashlight)))
).Aggregate((oldmax, cur) => cur.Flashlight > oldmax.Flashlight ? cur : oldmax);
return final;
}
}
public class Toy
{
public string Name { get; set; }
public int Time { get; set; }
public Toy(string name, int time)
{
Name = name;
Time = time;
}
}
public class State
{
public Toy[] Start { get; private set; }
public Toy[] Finish { get; private set; }
public int Flashlight { get; private set; }
public string Message { get; private set; }
public State(IEnumerable<Toy> start, IEnumerable<Toy> finish, int flashlight, string message)
{
Start = start.ToArray();
Finish = finish.ToArray();
Flashlight = flashlight;
Message = message;
}
}
}
答案 1 :(得分:1)
唯一的解决方案是:
* Buzz and Woody go right
* Buzz goes left
* Hamm and Rex go right
* Woody goes left
* Woody and Buzz go right
和
* Buzz and Woody go right
* Woody goes left
* Hamm and Rex go right
* Buzz goes left
* Woody and Buzz go right
使用它们检查您的问题是否给出了正确的结果。
答案 2 :(得分:0)
你刚刚让我知道我使用AI算法的形状有多么糟糕:(
我总是和最快的家伙一起回来......有点作弊,但我现在太累了让它适用于所有组合。这是我使用BFS的解决方案。
class Program
{
private class Toy
{
public string Name { get; set; }
public int Time { get; set; }
}
private class Node : IEquatable<Node>
{
public Node()
{
Start = new List<Toy>();
End = new List<Toy>();
}
public Node Clone()
{
return new Node
{
Start = new List<Toy>(Start),
End = new List<Toy>(End),
Time = Time,
Previous = this
};
}
public int Time { get; set; }
public List<Toy> Start { get; set; }
public List<Toy> End { get; set; }
public Node Previous { get; set; }
public Toy Go1 { get; set; }
public Toy Go2 { get; set; }
public Toy Return { get; set; }
public bool Equals(Node other)
{
return Start.TrueForAll(t => other.Start.Contains(t)) &&
End.TrueForAll(t => other.End.Contains(t)) &&
Time == other.Time;
}
}
private static void GenerateNodes(Node node, Queue<Node> open, List<Node> closed)
{
foreach(var toy1 in node.Start)
{
foreach(var toy2 in node.Start.Where(t => t != toy1))
{
var newNode = node.Clone();
newNode.Start.Remove(toy1);
newNode.Start.Remove(toy2);
newNode.End.Add(toy1);
newNode.End.Add(toy2);
newNode.Go1 = toy1;
newNode.Go2 = toy2;
newNode.Time += Math.Max(toy1.Time, toy2.Time);
if(newNode.Time <= 60 && !closed.Contains(newNode) && !open.Contains(newNode))
{
open.Enqueue(newNode);
}
}
}
}
static void Main(string[] args)
{
var open = new Queue<Node>();
var closed = new List<Node>();
var initial = new Node
{
Start = new List<Toy>
{
new Toy {Name = "Buzz", Time = 5},
new Toy {Name = "Woody", Time = 10},
new Toy {Name = "Rex", Time = 20},
new Toy {Name = "Ham", Time = 25}
}
};
open.Enqueue(initial);
var resultNodes = new List<Node>();
while(open.Count != 0)
{
var current = open.Dequeue();
closed.Add(current);
if(current.End.Count == 4)
{
resultNodes.Add(current);
continue;
}
if(current.End.Count != 0)
{
var fastest = current.End.OrderBy(t => t.Time).First();
current.End.Remove(fastest);
current.Start.Add(fastest);
current.Time += fastest.Time;
current.Return = fastest;
}
GenerateNodes(current, open, closed);
}
foreach(var result in resultNodes)
{
var path = new List<Node>();
var node = result;
while(true)
{
if(node.Previous == null) break;
path.Insert(0, node);
node = node.Previous;
}
path.ForEach(n => Console.WriteLine("Went: {0} {1}, Came back: {2}, Time: {3}", n.Go1.Name, n.Go2.Name, n.Return != null ? n.Return.Name : "nobody", n.Time));
Console.WriteLine(Environment.NewLine);
}
Console.ReadLine();
}
}
答案 3 :(得分:0)
我没有实施,但这里的解决方案如何运作:
你总是把最快的一对发送到另一边并且在另一边返回最快的一对,但是你永远不会发送相同的一次2次(除非每个人都被发送了2次,然后你只发送了最快2次)标记他(让他的时间在地狱里)
这可以通过2 Priority Queue
s(O(n log) n
解决方案时间)来完成。
您案件的解决方案:
P-Q 1 P-Q 2 Buzz Woody Rex Hamm Buzz + Woody go = 10 min P-Q 1 P-Q 2 Rex Buzz Hamm Woody Buzz goes back = 5 min P-Q 1 P-Q 2 Hamm Woody Rex * Buzz Hamm + Rex go = 25 min P-Q 1 P-Q 2 * Buzz Woody Hamm Rex Woody comes back = 10 min P-Q 1 P-Q 2 * Buzz Hamm * Woody Rex Woddy + Buzz go = 10 min --------------------------- Total: 60 mins
例如,对于6种变体,您将执行以下操作:
1 - fastest 2 - after fastest 3 - you got it 4 5 6 - slowest 1 + 2 go 1 goes back 3 + 4 go 2 goes back 5 + 6 go 3 goes back 1 + 2 go 1 goes back 1 + 3 go