在工作中以及在游戏中的某一时刻进行游戏时,玩家会被投入奖励游戏中。他们需要赢取的金额是预先确定的,但是我们想提出一种算法,该算法使用加法,乘法和除法以x步的数量达到该金额。步骤的数量也将提前知道,因此算法只需要弄清楚如何使用该数量的步骤即可达到数量。
您只能使用+1到+ 15,x2,x4,/ 2,/ 4。您可以在步骤中超出目标数目,但必须在最后一步中达到目标数目。步长通常在15到30之间,并且您始终从0开始。
例如:Amount:100,Steps:10 == + 10,+ 2,x2,+ 4,x4,+ 10,/ 2,+ 15,+ 15,+ 9
数量:40,步数:12 == +15,+1,+5,+2,+1,/ 2, 4,+6,+6,/ 4,+5, 2
我很好奇是否已经存在这样的东西?我确定我们可以提出一些建议,但是如果有通用的算法可以完成这项工作,我就不想重新发明轮子。
更新:对@FryGuy的代码进行了一些小的更改,使其到达随机到达目标编号所需的路线。他的解决方案按原样运作良好,但是在看到它可行并考虑@Argote和@Moron的评论之后,我意识到它需要具有一定的随机性,以使其吸引我们的玩家。在10个步骤中增加+1以达到10个目标效果很好,但是就我们的使用方式而言,这很“无聊”。非常感谢所有发表评论和回答的人。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CR { class Program { static void Main(string[] args) { while (true) { int targetNumber = 20; int steps = 13; int[] route = null; Boolean routeAcceptable = false; // Continue choosing routes until we find one that is acceptable (doesn't average above or target win, but does exceed it at least once) while(!routeAcceptable) { routeAcceptable = CalculateRoute(targetNumber, steps, out route) && route.Average() < targetNumber && route.Max() > targetNumber; } foreach (int i in route.Reverse()) { Console.WriteLine(i); } Console.WriteLine("-----------------------"); Console.ReadLine(); } } static Boolean CalculateRoute(int targetNumber, int numSteps, out int[] route) { int maxValue = targetNumber * 16; bool[,] reachable = new bool[numSteps + 1, maxValue]; // build up the map reachable[0, 0] = true; for (int step = 0; step < numSteps; step++) { for (int n = 0; n < maxValue; n++) { if (reachable[step, n]) { foreach (int nextNum in ReachableNumbersFrom(n)) { if (nextNum < maxValue && nextNum > 0) { reachable[step + 1, nextNum] = true; } } } } } // figure out how we got there int[] routeTaken = new int[numSteps + 1]; int current = targetNumber; for (int step = numSteps; step >= 0; step--) { routeTaken[step] = current; bool good = false; // Randomize the reachable numbers enumeration to make the route 'interesting' foreach (int prev in RandomizedIEnumerbale(ReachableNumbersFromReverse(current))) { if (prev < targetNumber * 8) { if (reachable[step, prev]) { current = prev; good = true; // Avoid hitting the same number twice, again to make the route 'interesting' for (int c = numSteps; c >= 0; c--) { reachable[c, prev] = false; } break; } } } if (!good) { route = routeTaken; return false; } } route = routeTaken; return true; } static IEnumerable<int> ReachableNumbersFrom(int n) { // additions for (int i = 1; i <= 15; i++) { yield return n + i; } // mults/divides yield return n / 2; yield return n / 4; yield return n * 2; yield return n * 4; } static IEnumerable<int> ReachableNumbersFromReverse(int n) { // additions for (int i = 1; i <= 15; i++) { if (n - i >= 0) yield return n - i; } // mults/divides if (n % 2 == 0) yield return n / 2; if (n % 4 == 0) yield return n / 4; yield return n * 2; yield return n * 4; } static IEnumerable<int> RandomizedIEnumerbale(IEnumerable<int> enumerbale) { Random random = new Random(System.DateTime.Now.Millisecond); return ( from r in ( from num in enumerbale select new { Num = num, Order = random.Next() } ) orderby r.Order select r.Num ); } } }
我会使用动态编程。首先,建立一个地图,列出每个步骤可以到达的数字,然后回溯以找出如何到达那里:
void CalculateRoute(int targetNumber, int numSteps) { int maxValue = targetNumber * 16; bool[,] reachable = new bool[numSteps + 1, maxValue]; // build up the map reachable[0, 0] = true; for (int step = 0; step < numSteps; step++) { for (int n = 0; n < maxValue; n++) { if (reachable[step, n]) { foreach (int nextNum in ReachableNumbersFrom(n)) { if (nextNum < maxValue && nextNum >= 0) reachable[step + 1, nextNum] = true; } } } } // figure out how we got there int current = targetNumber; for (int step = numSteps; step >= 0; step--) { Console.WriteLine(current); bool good = false; foreach (int prev in ReachableNumbersFromReverse(current)) { if (reachable[step, prev]) { current = prev; good = true; break; } } if (!good) { Console.WriteLine("Unable to proceed"); break; } } } IEnumerable<int> ReachableNumbersFrom(int n) { // additions for (int i = 1; i <= 15; i++) yield return n + i; // mults/divides yield return n / 2; yield return n / 4; yield return n * 2; yield return n * 4; } IEnumerable<int> ReachableNumbersFromReverse(int n) { // additions for (int i = 1; i <= 15; i++) yield return n - i; // mults/divides if (n % 2 == 0) yield return n / 2; if (n % 4 == 0) yield return n / 4; yield return n * 2; yield return n * 4; }