Рекурсия расписания турниров Java
Я работаю над домашним заданием для своего класса Java, и я зациклился на том, как настроить рекурсию (требуется), чтобы она работала. Мы должны запросить у пользователя ряд "n" конкурентов (предположим, что это должно быть сила 2, нам не нужно проверять правильность ввода пользователя). Каждая команда должна играть каждую команду только один раз. Выход для n = 8 должен быть:
1 2 3 4 5 6 7 8
2 1 4 3 6 5 8 7
3 4 1 2 7 8 5 6
4 3 2 1 8 7 6 5
5 6 7 8 1 2 3 4
6 5 8 7 2 1 4 3
7 8 5 6 3 4 1 2
8 7 6 5 4 3 2 1
Единственным параметром, который я могу передать методу, является "int n". Так что, если есть 16 команд (т.е. N = 16), то второй вызов будет проходить 8, затем пропустить 4, затем 2 и, наконец, 1.
Итак, исходя из этого, я понимаю, что каждая другая строка просто переворачивает каждую пару чисел. Итак, для 2 ^ 0 есть только одна команда. Для 2 ^ 1 это:
1 2
2 1
Для 2 ^ 2 это 4 команды, но команды 3 и 4 имеют ту же рекурсию, что и команды 1 и 2. Затем вы меняете их так, чтобы 3 и 4 приходили до 1 и 2, а затем вы меняли отдельные пары снова
1 2 3 4
2 1 4 3
3 4 1 2
4 3 2 1
Итак, вы можете разбить диаграмму на 4 равных угла, и каждый противоположный угол равен друг другу.
За последние пару дней я прошел через несколько вариантов моего кода, но вот где я сейчас. Это на самом деле шаг назад от того места, где я был, но я изначально пытался передать стартовую строку и начальный столбец, но мне сообщили, что я не должен этого делать, и просто передаю n рекурсивно.
class MyArray {
final int MAXROW = 32, MAXCOL = 32;
int A[][]; //reference variable
int nR, nC; //number of integers in A, <= MAXSIZE
//constructor
MyArray() {
A = new int[MAXROW] [MAXCOL];
nR = nC = 0;
}
void schedule(int n) {
if (n > 1) {
schedule(n/2);
for (int r = 0; r < n/2; r++)
for (int c = 0; c < n/2; c++) {
A[r+n][c] = A[r][c+n];
A[r+n][c+n] = A[r][c];
}
}
}
void printA() {
printA(nC-1)
}
void printA(int n) {
if (n >= 0) {
printA(n-1);
for (int c = 0; c < nC; c++)
System.out.printf("%3d", (A[n][c]));
System.out.println();
}
}
Ответы
Ответ 1
Наконец понял это. Вот код для метода расписания, красивый и короткий и сладкий, в основном, верхние левые значения + (n/2) = верхние правые и нижние левые значения. Нижние правые значения = верхние левые значения.
void schedule(int n) {
if (n > 0) {
schedule(n/2);
if (n == 1)
A[0][0] = 1;
else {
for (int r = 0; r < n/2; r++)
for (int c = 0; c < n/2; c++) {
A[r][c+(n/2)] = A[r][c] + (n/2);
A[r+(n/2)][c] = A[r][c] + (n/2);
A[r+(n/2)][c+(n/2)] = A[r][c];
}
}
}
}
Ответ 2
Я не смог исправить свой код..... мое решение:
![recursive]()
public class MyArray {
final int MAXROW = 32, MAXCOL = 32;
int A[][]; //reference variable
MyArray() {
A = new int[MAXROW][MAXCOL];
}
public static void main(String[] args) {
MyArray m = new MyArray();
int n = 8;
m.mySchedule(n);
m.printA(n);
}
void mySchedule(int n) {
mySchedule(n, 0, 0, n);
}
void mySchedule(int n, int row, int col, int carry) {
if (n == 1) {
A[row][col] = carry; //Trivial Case
} else {
//divide the problem into 4 subproblems
int k = n / 2;
mySchedule(k, row, col, carry - k);
mySchedule(k, row, col + k, carry);
mySchedule(k, row + k, col, carry);
mySchedule(k, row + k, col + k, carry - k);
}
}
void printA(int n) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
System.out.print(A[i][j] + "\t");
}
System.out.println();
}
}
}
Ответ 3
Вот моя текущая версия кода. Мой профессор все еще говорит, что он может быть более эффективным, удалив 2-й рекурсивный вызов. Я включил все свои комментарии, поэтому я вспомнил, что на самом деле делали.
class MySchedule {
final int MAXSIZE = 32;
int A[][]; //reference variable
int max; //number of integers in A, <= MAXSIZE
int row = 1; //keeps track of rows during recursion, row 0 set during user input
//constructor
MySchedule() {
A = new int[MAXSIZE] [MAXSIZE];
max = 0;
}
/*
if teams = 4, then movements per row are: 2^0, 2^1, 2^0
if teams = 8: 2^0, 2^1, 2^0, 2^2, 2^0, 2^1, 2^0
(n/2) gives us the correct power to calculate movements
for each value of n, we move n places in either direction
for loop iterates ever 2*n
outer loop is for each iteration
inner loops are each number of movements for each iteration
*/
void schedule(int n) {
if (n >= 1) {
schedule(n/2);
//start at column 0 for each row
int col = 0;
for (int i = 0; i < max; i += (2*n)) {
//current position uses value from previous n rows/columns.
for (int j = 0; j < n; j++)
A[row][col+j] = A[row-n][col+j+n];
for (int j = n; j < n*2; j++)
A[row][col+j] = A[row-n][col+j-n];
col += 2*n;
}
row++;
if (n > 1)
schedule(n/2);
}
}
void printA() {
//print header, then print team schedule
System.out.printf("%4s", "day");
System.out.printf("%12s", "teams");
System.out.println();
printA(max-1);
}
void printA(int n) {
if (n >= 0) {
printA(n-1);
//n=0 is the row to list the teams.
//Following rows indicate which team they play on which day
if (n == 0)
System.out.printf("%4s", "");
if (n >= 1)
System.out.printf("%4s", "D"+n);
for (int c = 0; c < max; c++)
System.out.printf("%3d", (A[n][c]));
System.out.println();
}
}
}
public class Hw10 {
//determine if n is a 2 power
static boolean isPow(int n) {
while (n > 1) {
if (n%2 != 0)
return false;
n = n / 2;
}
return true;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int teams;
//prompt user input for teams and print schedule
do {
System.out.print("How many teams (0 to exit): ");
teams = in.nextInt();
//check to make sure user input is a power of 2.
do {
if (isPow(teams) == false) {
System.out.println("Invalid input, must be a power of 2.");
System.out.print("How many teams (0 to exit): ");
teams = in.nextInt();
}
} while (isPow(teams) == false);
//initialize array to avoid out of bounds errors on repeat tries
MySchedule sched = new MySchedule();
//initialize first row of array with number of teams
for (int i = 0; i < teams; i++)
sched.A[0][i] = i+1;
sched.max = teams;
sched.schedule(teams/2);
sched.printA();
System.out.println();
} while (teams > 0);
}
}