diff --git a/backend/main.py b/backend/main.py
index 14e41bf..3432e1c 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -24,3 +24,11 @@ from routers import n_queens_router
app.include_router(n_queens_router.router)
from routers import knapsack_router
app.include_router(knapsack_router.router)
+from routers import min_path_sum_router
+app.include_router(min_path_sum_router.router)
+from routers import flower_planting_router
+app.include_router(flower_planting_router.router)
+from routers import advantage_shuffle_router
+app.include_router(advantage_shuffle_router.router)
+
+
diff --git a/backend/problems/advantage_shuffle/generator.py b/backend/problems/advantage_shuffle/generator.py
new file mode 100644
index 0000000..f0f0661
--- /dev/null
+++ b/backend/problems/advantage_shuffle/generator.py
@@ -0,0 +1,7 @@
+import random
+from typing import List
+
+def generate_advantage_shuffle_case(size: int = 10, max_val: int = 100) -> dict:
+ nums1 = [random.randint(0, max_val) for _ in range(size)]
+ nums2 = [random.randint(0, max_val) for _ in range(size)]
+ return {"nums1": nums1, "nums2": nums2}
diff --git a/backend/problems/advantage_shuffle/problem.py b/backend/problems/advantage_shuffle/problem.py
new file mode 100644
index 0000000..5e68f7f
--- /dev/null
+++ b/backend/problems/advantage_shuffle/problem.py
@@ -0,0 +1,50 @@
+from typing import Any, Dict, List
+from common.base_problem import BaseProblem
+from problems.advantage_shuffle.generator import generate_advantage_shuffle_case
+from problems.advantage_shuffle.solvers import solve_greedy, solve_brute_force, solve_random
+from common.timer_utils import time_execution
+
+class AdvantageShuffleProblem(BaseProblem):
+ def generate_case(self, size: int = 10, max_val: int = 100) -> Dict[str, Any]:
+ return generate_advantage_shuffle_case(size, max_val)
+
+ def solve(self, input_data: Dict[str, Any], algorithm: str) -> Dict[str, Any]:
+ nums1 = input_data.get("nums1", [])
+ nums2 = input_data.get("nums2", [])
+
+ result = None
+ duration = 0.0
+
+ if algorithm == "greedy":
+ result, duration = time_execution(solve_greedy)(nums1, nums2)
+ elif algorithm == "brute_force":
+ result, duration = time_execution(solve_brute_force)(nums1, nums2)
+ elif algorithm == "random":
+ result, duration = time_execution(solve_random)(nums1, nums2)
+ else:
+ raise ValueError(f"Unknown algorithm: {algorithm}")
+
+ # Calculate advantage score
+ score = sum(1 for a, b in zip(result, nums2) if a > b)
+
+ return {
+ "algorithm": algorithm,
+ "shuffled_nums1": result,
+ "advantage_score": score,
+ "time_seconds": duration
+ }
+
+ def verify(self, input_data: Any, result: Any) -> bool:
+ # Verification is hard because there might be multiple optimal solutions.
+ # We can verify that the score matches the greedy score (which is optimal).
+ nums1 = input_data.get("nums1", [])
+ nums2 = input_data.get("nums2", [])
+
+ greedy_res, _ = time_execution(solve_greedy)(nums1, nums2)
+ max_score = sum(1 for a, b in zip(greedy_res, nums2) if a > b)
+
+ # If algorithm claims a score, is it correct based on its output?
+ output = result.get("shuffled_nums1", [])
+ actual_score = sum(1 for a, b in zip(output, nums2) if a > b)
+
+ return actual_score == result.get("advantage_score")
diff --git a/backend/problems/advantage_shuffle/solvers.py b/backend/problems/advantage_shuffle/solvers.py
new file mode 100644
index 0000000..c6a0824
--- /dev/null
+++ b/backend/problems/advantage_shuffle/solvers.py
@@ -0,0 +1,117 @@
+from typing import List
+
+def solve_greedy(nums1: List[int], nums2: List[int]) -> List[int]:
+ """
+ Greedy algorithm (Tian Ji Horse Racing strategy).
+ Sort nums1. Sort nums2 but keep track of original indices.
+ O(N log N)
+ """
+ n = len(nums1)
+ sorted_nums1 = sorted(nums1)
+ # Store (value, original_index) for nums2 to reconstruct answer order
+ sorted_nums2 = sorted([(val, i) for i, val in enumerate(nums2)])
+
+ res = [0] * n
+
+ # Two pointers for nums2 (weakest horse, strongest horse)
+ left_2, right_2 = 0, n - 1
+
+ # Iterate through our horses (nums1) from weakest to strongest?
+ # Actually standard implementation:
+ # Compare our weakest with their weakest.
+ # If ours > theirs, use it (win).
+ # Else, use our weakest to burn their strongest (lose).
+
+ # Let's use a deque or two pointers on nums1 as well?
+ # Actually, iterating nums1 from start to end (weakest to strongest) works with logic:
+ # If current nums1 can beat current weakest nums2, do it.
+ # Else, sacrifice current nums1 against current strongest nums2.
+
+ # Re-verification of strategy:
+ # We want to maximize wins.
+ # Consider our sorted nums1.
+ # Consider sorted nums2.
+ # If nums1[smallest] > nums2[smallest], we win! Assign nums1[smallest] to nums2[smallest]'s slot.
+ # If not, nums1[smallest] is useless for winning against weakest. Is it useful for anything?
+ # No, it's the worst horse. Sacrifice it against nums2[largest].
+
+ left_1, right_1 = 0, n - 1
+ left_2, right_2 = 0, n - 1
+
+ # We need to assign values to the original indices of nums2
+
+ # Wait, standard approach iterates nums1 (sorted) or nums2 (sorted)?
+ # Let's process nums1 from strongest to weakest? Or weakest to strongest?
+
+ # Let's use the standard LC 870 approach:
+ # Sort A. Sort B (with indices).
+ # For each b in sorted B (weakest to strongest):
+ # pick smallest a > b.
+ # If exists, use it.
+ # If not, use smallest a available (sacrifice).
+
+ # Better Tian Ji Logic:
+ # Compare our fastest with their fastest.
+ # If ours > theirs, win.
+ # Else (ours <= theirs), compare our slowest with their slowest.
+ # If ours > theirs, win.
+ # Else (ours <= theirs), race our slowest against their fastest.
+
+ # Let's implement the standard Greedy for "Advantage Shuffle" (Maximize A[i] > B[i] count):
+ # 1. Sort A.
+ # 2. Sort B with indices.
+ # 3. Use deque for A.
+ # Iterate B from strongest to weakest?
+ # Actually:
+ # Iterate B sorted (strongest to weakest).
+ # If A's strongest > B's strongest: Match them.
+ # Else: A's strongest cannot beat B's strongest. Nothing can.
+ # So sacrifice A's weakest against B's strongest.
+
+ import collections
+ deque_nums1 = collections.deque(sorted_nums1)
+ sorted_nums2_desc = sorted([(val, i) for i, val in enumerate(nums2)], key=lambda x: -x[0])
+
+ for val_b, idx_b in sorted_nums2_desc:
+ if deque_nums1[-1] > val_b:
+ res[idx_b] = deque_nums1.pop() # Strongest vs Strongest (Win)
+ else:
+ res[idx_b] = deque_nums1.popleft() # Weakest vs Strongest (Sacrifice)
+
+ return res
+
+def solve_random(nums1: List[int], nums2: List[int]) -> List[int]:
+ """
+ Random shuffling algorithm (Naive).
+ O(N) per attempt, but effectively random performance.
+ Just returns a random permutation of nums1.
+ """
+ import random
+ res = nums1[:]
+ random.shuffle(res)
+ return res
+
+def solve_brute_force(nums1: List[int], nums2: List[int]) -> List[int]:
+ """
+ Try all permutations of nums1 to find max advantage.
+ O(N!) - Extremely slow.
+ """
+ import itertools
+ n = len(nums1)
+
+ # Safety limit
+ if n > 8:
+ return solve_greedy(nums1, nums2)
+
+ max_score = -1
+ best_perm = []
+
+ for perm in itertools.permutations(nums1):
+ score = sum(1 for a, b in zip(perm, nums2) if a > b)
+ if score > max_score:
+ max_score = score
+ best_perm = list(perm)
+ if score == n: # Optimization: max possible found
+ break
+
+ return best_perm
diff --git a/backend/problems/flower_planting/generator.py b/backend/problems/flower_planting/generator.py
new file mode 100644
index 0000000..e51a092
--- /dev/null
+++ b/backend/problems/flower_planting/generator.py
@@ -0,0 +1,37 @@
+import random
+from typing import List
+
+def generate_flower_planting_case(length: int = 10, chance: float = 0.3) -> List[int]:
+ """
+ Generates a flowerbed array of 0s and 1s.
+ 0: Empty, 1: Planted.
+ Ensures no adjacent 1s (valid initial state).
+ """
+ flowerbed = [0] * length
+ for i in range(length):
+ if random.random() < chance:
+ # Check constraints
+ prev_empty = (i == 0) or (flowerbed[i-1] == 0)
+ # Since we fill left-to-right, we only check left neighbor carefully.
+ # But we must also ensure we don't invalidate a future planting?
+ # Actually, just randomly placing 1s might create invalid state (1,1).
+ # So we place 1 only if i-1 is 0.
+ if prev_empty:
+ flowerbed[i] = 1
+
+ # Double check right neighbor constraint (though we fill sequentially,
+ # randomness might need a second pass or careful construction.
+ # Simplified: construction guarantees i-1 is 0.
+ # But what if we place at i, and then at i+1?
+ # The loop above allows that. Let's fix logic.
+
+ flowerbed = [0] * length
+ i = 0
+ while i < length:
+ if random.random() < chance:
+ flowerbed[i] = 1
+ i += 2 # Skip next spot to maintain validity
+ else:
+ i += 1
+
+ return flowerbed
diff --git a/backend/problems/flower_planting/problem.py b/backend/problems/flower_planting/problem.py
new file mode 100644
index 0000000..8b2e87e
--- /dev/null
+++ b/backend/problems/flower_planting/problem.py
@@ -0,0 +1,46 @@
+from typing import Any, Dict, List
+import random
+from common.base_problem import BaseProblem
+from problems.flower_planting.generator import generate_flower_planting_case
+from problems.flower_planting.solvers import solve_greedy, solve_brute_force, max_flowers_greedy
+from common.timer_utils import time_execution
+
+class FlowerPlantingProblem(BaseProblem):
+ def generate_case(self, length: int = 10, n: int = 0) -> Dict[str, Any]:
+ flowerbed = generate_flower_planting_case(length)
+ # If n is not provided (or 0), generate a challenging but possible n
+ # We calculate max possible, then take a random portion of it or just use it.
+ # Let's just return the bed and let user/frontend specify n, OR generate a random N.
+ # Problem requires checking if n can be planted.
+ if n == 0:
+ max_possible = max_flowers_greedy(flowerbed)
+ # Randomly pick n between 0 and max_possible + 1 (to sometimes return False)
+ n = random.randint(0, max_possible + 1) if max_possible > 0 else 1
+
+ return {"flowerbed": flowerbed, "n": n}
+
+ def solve(self, input_data: Dict[str, Any], algorithm: str) -> Dict[str, Any]:
+ flowerbed = input_data.get("flowerbed", [])
+ n = input_data.get("n", 1)
+
+ result = None
+ duration = 0.0
+
+ if algorithm == "greedy":
+ result, duration = time_execution(solve_greedy)(flowerbed, n)
+ elif algorithm == "brute_force":
+ result, duration = time_execution(solve_brute_force)(flowerbed, n)
+ else:
+ raise ValueError(f"Unknown algorithm: {algorithm}")
+
+ return {
+ "algorithm": algorithm,
+ "can_plant": result,
+ "time_seconds": duration
+ }
+
+ def verify(self, input_data: Any, result: Any) -> bool:
+ flowerbed = input_data.get("flowerbed", [])
+ n = input_data.get("n", 1)
+ truth, _ = time_execution(solve_greedy)(flowerbed, n)
+ return result.get("can_plant") == truth
diff --git a/backend/problems/flower_planting/solvers.py b/backend/problems/flower_planting/solvers.py
new file mode 100644
index 0000000..fa4c4d3
--- /dev/null
+++ b/backend/problems/flower_planting/solvers.py
@@ -0,0 +1,76 @@
+from typing import List
+
+def solve_greedy(flowerbed: List[int], n: int) -> bool:
+ """
+ Greedy algorithm: Plant whenever possible.
+ O(N)
+ """
+ count = 0
+ # Operate on a copy to avoid modifying input in place if passed by reference
+ bed = flowerbed[:]
+ length = len(bed)
+
+ for i in range(length):
+ if bed[i] == 0:
+ empty_left = (i == 0) or (bed[i-1] == 0)
+ empty_right = (i == length - 1) or (bed[i+1] == 0)
+
+ if empty_left and empty_right:
+ bed[i] = 1
+ count += 1
+ if count >= n:
+ return True
+
+ return count >= n
+
+def solve_brute_force(flowerbed: List[int], n: int) -> bool:
+ """
+ Backtracking/Brute Force to see if N flowers can be planted.
+ O(2^N) - Highly inefficient, good for contrast.
+ """
+ length = len(flowerbed)
+
+ def can_plant(bed, index, remaining):
+ if remaining == 0:
+ return True
+ if index >= length:
+ return False
+
+ # Try planting at index
+ if bed[index] == 0:
+ empty_left = (index == 0) or (bed[index-1] == 0)
+ empty_right = (index == length - 1) or (bed[index+1] == 0)
+
+ if empty_left and empty_right:
+ # Option 1: Plant here
+ bed[index] = 1
+ if can_plant(bed, index + 2, remaining - 1):
+ return True
+ bed[index] = 0 # Backtrack
+
+ # Option 2: Don't plant here, try next spot
+ if can_plant(bed, index + 1, remaining):
+ return True
+
+ return False
+
+ # Safety for large inputs
+ if length > 25:
+ # Fallback
+ return solve_greedy(flowerbed, n)
+
+ return can_plant(flowerbed[:], 0, n)
+
+# Helper for just counting max flowers (often the core logic needed)
+def max_flowers_greedy(flowerbed: List[int]) -> int:
+ count = 0
+ bed = flowerbed[:]
+ length = len(bed)
+ for i in range(length):
+ if bed[i] == 0:
+ empty_left = (i == 0) or (bed[i-1] == 0)
+ empty_right = (i == length - 1) or (bed[i+1] == 0)
+ if empty_left and empty_right:
+ bed[i] = 1
+ count += 1
+ return count
diff --git a/backend/problems/min_path_sum/generator.py b/backend/problems/min_path_sum/generator.py
new file mode 100644
index 0000000..27d591b
--- /dev/null
+++ b/backend/problems/min_path_sum/generator.py
@@ -0,0 +1,8 @@
+import random
+from typing import List
+
+def generate_min_path_sum_case(rows: int = 5, cols: int = 5, min_val: int = 1, max_val: int = 20) -> List[List[int]]:
+ """
+ Generates a rows x cols grid with random integers.
+ """
+ return [[random.randint(min_val, max_val) for _ in range(cols)] for _ in range(rows)]
diff --git a/backend/problems/min_path_sum/problem.py b/backend/problems/min_path_sum/problem.py
new file mode 100644
index 0000000..dd0ac64
--- /dev/null
+++ b/backend/problems/min_path_sum/problem.py
@@ -0,0 +1,34 @@
+from typing import Any, Dict, List
+from common.base_problem import BaseProblem
+from problems.min_path_sum.generator import generate_min_path_sum_case
+from problems.min_path_sum.solvers import solve_dp, solve_recursion
+from common.timer_utils import time_execution
+
+class MinPathSumProblem(BaseProblem):
+ def generate_case(self, rows: int = 5, cols: int = 5, min_val: int = 1, max_val: int = 20) -> Dict[str, Any]:
+ grid = generate_min_path_sum_case(rows, cols, min_val, max_val)
+ return {"grid": grid}
+
+ def solve(self, input_data: Dict[str, Any], algorithm: str) -> Dict[str, Any]:
+ grid = input_data.get("grid", [])
+
+ result = None
+ duration = 0.0
+
+ if algorithm == "dp":
+ result, duration = time_execution(solve_dp)(grid)
+ elif algorithm == "recursion":
+ result, duration = time_execution(solve_recursion)(grid)
+ else:
+ raise ValueError(f"Unknown algorithm: {algorithm}")
+
+ return {
+ "algorithm": algorithm,
+ "min_path_sum": result,
+ "time_seconds": duration
+ }
+
+ def verify(self, input_data: Any, result: Any) -> bool:
+ grid = input_data.get("grid", [])
+ truth, _ = time_execution(solve_dp)(grid)
+ return result.get("min_path_sum") == truth
diff --git a/backend/problems/min_path_sum/solvers.py b/backend/problems/min_path_sum/solvers.py
new file mode 100644
index 0000000..52a8079
--- /dev/null
+++ b/backend/problems/min_path_sum/solvers.py
@@ -0,0 +1,56 @@
+from typing import List
+
+def solve_dp(grid: List[List[int]]) -> int:
+ """
+ Dynamic Programming solution for Minimum Path Sum.
+ O(M * N)
+ """
+ if not grid or not grid[0]:
+ return 0
+
+ rows, cols = len(grid), len(grid[0])
+ dp = [[0] * cols for _ in range(rows)]
+
+ dp[0][0] = grid[0][0]
+
+ # Initialize first row
+ for j in range(1, cols):
+ dp[0][j] = dp[0][j-1] + grid[0][j]
+
+ # Initialize first column
+ for i in range(1, rows):
+ dp[i][0] = dp[i-1][0] + grid[i][0]
+
+ # Fill the rest
+ for i in range(1, rows):
+ for j in range(1, cols):
+ dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
+
+ return dp[rows-1][cols-1]
+
+def solve_recursion(grid: List[List[int]]) -> int:
+ """
+ Recursive Brute Force solution (Top-Down without Memoization).
+ O(2^(M+N))
+ Only for very small inputs!
+ """
+ if not grid or not grid[0]:
+ return 0
+
+ rows, cols = len(grid), len(grid[0])
+
+ # Safety check to prevent freezing/recursion depth errors on large inputs if called accidentally
+ if rows + cols > 18:
+ # Fallback to DP for safety if input is too large for naive recursion
+ return solve_dp(grid)
+
+ def helper(r, c):
+ if r == 0 and c == 0:
+ return grid[0][0]
+
+ if r < 0 or c < 0:
+ return float('inf')
+
+ return grid[r][c] + min(helper(r-1, c), helper(r, c-1))
+
+ return helper(rows-1, cols-1)
diff --git a/backend/routers/advantage_shuffle_router.py b/backend/routers/advantage_shuffle_router.py
new file mode 100644
index 0000000..067f1e2
--- /dev/null
+++ b/backend/routers/advantage_shuffle_router.py
@@ -0,0 +1,75 @@
+from fastapi import APIRouter
+from pydantic import BaseModel
+from typing import List, Any
+from problems.advantage_shuffle.problem import AdvantageShuffleProblem
+
+router = APIRouter(
+ prefix="/advantage_shuffle",
+ tags=["advantage_shuffle"],
+ responses={404: {"description": "Not found"}},
+)
+
+problem_solver = AdvantageShuffleProblem()
+
+class GenerateRequest(BaseModel):
+ size: int = 10
+ max_val: int = 100
+
+class SolveRequest(BaseModel):
+ nums1: List[int]
+ nums2: List[int]
+ algorithms: List[str] = ["greedy", "brute_force", "random"]
+
+class BenchmarkRequest(BaseModel):
+ sizes: List[int] = [5, 8, 100, 1000]
+ algorithms: List[str] = ["greedy", "brute_force", "random"]
+
+@router.post("/generate")
+async def generate_case(req: GenerateRequest):
+ return problem_solver.generate_case(size=req.size, max_val=req.max_val)
+
+@router.post("/solve")
+async def solve_case(req: SolveRequest):
+ input_data = {"nums1": req.nums1, "nums2": req.nums2}
+ results = []
+
+ for algo in req.algorithms:
+ try:
+ if algo == "brute_force" and len(req.nums1) > 8:
+ results.append({
+ "algorithm": algo,
+ "error": "Input too large for Brute Force (limit 8)",
+ "skipped": True
+ })
+ continue
+
+ res = problem_solver.solve(input_data, algo)
+ results.append(res)
+ except Exception as e:
+ results.append({"algorithm": algo, "error": str(e)})
+ return results
+
+@router.post("/benchmark")
+async def benchmark(req: BenchmarkRequest):
+ benchmark_results = []
+ for size in req.sizes:
+ input_data = problem_solver.generate_case(size=size)
+
+ size_result = {"size": size, "algorithms": []}
+ for algo in req.algorithms:
+ try:
+ if algo == "brute_force" and size > 8:
+ size_result["algorithms"].append({
+ "algorithm": algo,
+ "time_seconds": None,
+ "skipped": True
+ })
+ continue
+
+ res = problem_solver.solve(input_data, algo)
+ size_result["algorithms"].append(res)
+ except Exception as e:
+ size_result["algorithms"].append({"algorithm": algo, "error": str(e)})
+
+ benchmark_results.append(size_result)
+ return benchmark_results
diff --git a/backend/routers/flower_planting_router.py b/backend/routers/flower_planting_router.py
new file mode 100644
index 0000000..700e01d
--- /dev/null
+++ b/backend/routers/flower_planting_router.py
@@ -0,0 +1,75 @@
+from fastapi import APIRouter
+from pydantic import BaseModel
+from typing import List, Any
+from problems.flower_planting.problem import FlowerPlantingProblem
+
+router = APIRouter(
+ prefix="/flower_planting",
+ tags=["flower_planting"],
+ responses={404: {"description": "Not found"}},
+)
+
+problem_solver = FlowerPlantingProblem()
+
+class GenerateRequest(BaseModel):
+ length: int = 10
+ n: int = 0 # 0 means auto-generate challenging N
+
+class SolveRequest(BaseModel):
+ flowerbed: List[int]
+ n: int
+ algorithms: List[str] = ["greedy", "brute_force"]
+
+class BenchmarkRequest(BaseModel):
+ sizes: List[int] = [10, 15, 20, 25]
+ algorithms: List[str] = ["greedy", "brute_force"]
+
+@router.post("/generate")
+async def generate_case(req: GenerateRequest):
+ return problem_solver.generate_case(length=req.length, n=req.n)
+
+@router.post("/solve")
+async def solve_case(req: SolveRequest):
+ input_data = {"flowerbed": req.flowerbed, "n": req.n}
+ results = []
+
+ for algo in req.algorithms:
+ try:
+ if algo == "brute_force" and len(req.flowerbed) > 25:
+ results.append({
+ "algorithm": algo,
+ "error": "Input too large for Brute Force (limit 25)",
+ "skipped": True
+ })
+ continue
+
+ res = problem_solver.solve(input_data, algo)
+ results.append(res)
+ except Exception as e:
+ results.append({"algorithm": algo, "error": str(e)})
+ return results
+
+@router.post("/benchmark")
+async def benchmark(req: BenchmarkRequest):
+ benchmark_results = []
+ for size in req.sizes:
+ input_data = problem_solver.generate_case(length=size)
+
+ size_result = {"size": size, "algorithms": []}
+ for algo in req.algorithms:
+ try:
+ if algo == "brute_force" and size > 25:
+ size_result["algorithms"].append({
+ "algorithm": algo,
+ "time_seconds": None,
+ "skipped": True
+ })
+ continue
+
+ res = problem_solver.solve(input_data, algo)
+ size_result["algorithms"].append(res)
+ except Exception as e:
+ size_result["algorithms"].append({"algorithm": algo, "error": str(e)})
+
+ benchmark_results.append(size_result)
+ return benchmark_results
diff --git a/backend/routers/min_path_sum_router.py b/backend/routers/min_path_sum_router.py
new file mode 100644
index 0000000..78fc389
--- /dev/null
+++ b/backend/routers/min_path_sum_router.py
@@ -0,0 +1,82 @@
+from fastapi import APIRouter, HTTPException
+from pydantic import BaseModel
+from typing import List, Optional, Dict, Any
+from problems.min_path_sum.problem import MinPathSumProblem
+
+router = APIRouter(
+ prefix="/min_path_sum",
+ tags=["min_path_sum"],
+ responses={404: {"description": "Not found"}},
+)
+
+problem_solver = MinPathSumProblem()
+
+class GenerateRequest(BaseModel):
+ rows: int = 5
+ cols: int = 5
+ min_val: int = 1
+ max_val: int = 20
+
+class SolveRequest(BaseModel):
+ grid: List[List[int]]
+ algorithms: List[str] = ["dp", "recursion"]
+
+class BenchmarkRequest(BaseModel):
+ sizes: List[int] = [4, 6, 8, 10, 12] # Assuming square grids for simplicity in benchmark input, or handle appropriately
+ algorithms: List[str] = ["dp", "recursion"]
+
+@router.post("/generate")
+async def generate_case(req: GenerateRequest):
+ return problem_solver.generate_case(rows=req.rows, cols=req.cols, min_val=req.min_val, max_val=req.max_val)
+
+@router.post("/solve")
+async def solve_case(req: SolveRequest):
+ input_data = {"grid": req.grid}
+ results = []
+
+ # Check dimensions for safety check if needed
+ rows = len(req.grid)
+ cols = len(req.grid[0]) if rows > 0 else 0
+
+ for algo in req.algorithms:
+ try:
+ # Recursion safety limit
+ if algo == "recursion" and (rows + cols > 18):
+ results.append({
+ "algorithm": algo,
+ "error": "Input too large for Recursion (limit rows+cols <= 18)",
+ "skipped": True
+ })
+ continue
+
+ res = problem_solver.solve(input_data, algo)
+ results.append(res)
+ except ValueError as e:
+ results.append({"algorithm": algo, "error": str(e)})
+ return results
+
+@router.post("/benchmark")
+async def benchmark(req: BenchmarkRequest):
+ benchmark_results = []
+ for size in req.sizes:
+ # Use size as both rows and cols for benchmarking
+ input_data = problem_solver.generate_case(rows=size, cols=size)
+
+ size_result = {"size": size, "algorithms": []}
+ for algo in req.algorithms:
+ try:
+ if algo == "recursion" and (size + size > 18):
+ size_result["algorithms"].append({
+ "algorithm": algo,
+ "time_seconds": None,
+ "skipped": True
+ })
+ continue
+
+ res = problem_solver.solve(input_data, algo)
+ size_result["algorithms"].append(res)
+ except Exception as e:
+ size_result["algorithms"].append({"algorithm": algo, "error": str(e)})
+
+ benchmark_results.append(size_result)
+ return benchmark_results
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 5dbe349..1e82ff4 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -3,6 +3,9 @@ import MaxSubarray from './components/MaxSubarray';
import IntervalScheduling from './components/IntervalScheduling';
import NQueens from './components/NQueens';
import Knapsack from './components/Knapsack';
+import MinPathSum from './components/MinPathSum';
+import FlowerPlanting from './components/FlowerPlanting';
+import AdvantageShuffle from './components/AdvantageShuffle';
function App() {
const [activeTab, setActiveTab] = useState('max_subarray');
@@ -51,6 +54,33 @@ function App() {
>
0/1 背包
+
+
+
@@ -63,8 +93,22 @@ function App() {
{activeTab === 'interval_scheduling' &&
目标:给定两个数组 A 和 B,重新排列 A,使得 A[i] {'>'} B[i] 的索引数目最大化。
+ + {/* Algorithm Selection */} +| 算法 | +胜场数 (Advantage) | +耗时 (秒) | +
|---|---|---|
| {res.algorithm} | +{res.advantage_score} | +{res.time_seconds?.toFixed(6)} | +
目标:判断在不打破种植规则(花不能相邻)的情况下,能否在花坛中再种下 N 朵花。
+ + {/* Algorithm Selection */} +长度: {currentCase.length}
+| 算法 | +能否种下? | +耗时 (秒) | +
|---|---|---|
| {res.algorithm} | ++ {res.can_plant === true ? 是 : + res.can_plant === false ? 否 : '-'} + | +{res.time_seconds?.toFixed(6)} | +
目标:寻找从网格左上角到右下角的路径,使得路径上的数字总和最小。每次只能向下或向右移动。
+ + {/* Algorithm Selection */} +| {val} | + ))} +
规模: {currentCase.length} x {currentCase[0].length}
+| 算法 | +最小路径和 | +耗时 (秒) | +
|---|---|---|
| {res.algorithm} | +{res.min_path_sum} | +{res.time_seconds?.toFixed(6)} | +