Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 31.03.2019, 22:13   #1
xNos
 
Регистрация: 05.03.2018
Сообщений: 4
По умолчанию Динамическое программирование в трёхмерном массиве

Здравствуйте
Это классическая задача дп, только в трёхмерном массиве. В нём нужно найти такой путь из левого верхнего угла в правый нижний ( из (1, 1, 1) в (m, n, t)), чтобы сумма чисел по данному пути была минимальной. Двигаться можно только вправо, вниз, либо внутрь.
Думал, что решил задачу, пока не поменял массив.
Проблема в том, что правильно пересчитывается только первая матрица, в других могут оставаться несколько тех же самых чисел.
Смотрел решения задач в двумерном массиве, вроде, понимал, пытался что-то исправить, но безрезультатно, что-то пишу и уже сам не понимаю, что делаю.
Вот код. В файле в первой строке написаны размеры, далее сам массив.
Код:
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	const int n1 = 21, n2 = 21, n3 = 21;
	int arr[n1][n2][n3];
	int b[n1][n2][n3];
	ifstream fin("input.txt");
	int m, n, t;
	fin >> m >> n >> t;

	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			for (int k = 1; k <= t; k++) {
				fin >> arr[i][j][k];
				b[i][j][k] = arr[i][j][k];
				cout << '\t' << arr[i][j][k];
			}
			cout << endl;
		}
		cout << endl;
	}
	for (int i = 0; i <= m; i++) { 
		for (int j = 0; j <= n; j++) {
			for (int k = 0; k <= t; k++) {
				b[i][j][0] = INT_MAX;
				b[i][0][k] = INT_MAX;
				b[0][j][k] = INT_MAX;
			}
		}
	}

	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			for (int k = 1; k <= t; k++) {
				
					if (b[i - 1][j][k] < b[i][j - 1][k] &&
						b[i - 1][j][k] < b[i][j][k - 1]) {
						b[i][j][k] = b[i - 1][j][k] + arr[i][j][k];
					}
					else if (b[i][j - 1][k] < b[i - 1][j][k] &&
						b[i][j - 1][k] < b[i][j][k - 1]) {
						b[i][j][k] = b[i][j - 1][k] + arr[i][j][k];
					}
					else if (b[i][j][k - 1] < b[i - 1][j][k] &&
						b[i][j][k - 1] < b[i][j - 1][k]) {
						b[i][j][k] = b[i][j][k - 1] + arr[i][j][k];
					}
					cout << '\t' << "pos(" << i << "," << j << "," << k << ")" << b[i][j][k];
			}
			cout << endl;
		}
		cout << endl;
	}
	cout << "--------------" << endl;
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			for (int k = 1; k <= t; k++) {
				
				cout << '\t' << b[i][j][k];
			}
			cout << endl;
		}
		cout << endl;
	}
	system("pause");
	return 0;
}
Пример файла input.txt:
4 4 3

1 4 8
2 3 10
5 1 7
6 4 5

8 3 18
17 5 1
8 16 4
3 11 9

8 3 10
14 3 20
20 8 14
4 23 3

13 8 10
8 19 16
15 29 1
17 10 6

Последний раз редактировалось xNos; 01.04.2019 в 00:08. Причина: Ошибка в формулировке
xNos вне форума Ответить с цитированием
Старый 31.03.2019, 23:14   #2
Bugrimov
C/C++, Java
Участник клуба
 
Аватар для Bugrimov
 
Регистрация: 28.03.2012
Сообщений: 1,679
По умолчанию

Интересно, напоминает поиск кратчайшего пути в графе
"Keep it simple" - придерживайтесь простоты!
Уильям Оккам - "Не следует множить сущее без необходимости"
Сложность - враг простоты и удобства!
Bugrimov вне форума Ответить с цитированием
Старый 02.04.2019, 22:54   #3
xNos
 
Регистрация: 05.03.2018
Сообщений: 4
По умолчанию

Немного прояснилась проблема. Когда считывал файл, то намудрил с измерениями и не так с ними работал, но это не главное
Программа работает, но есть неприятный нюанс:
Не пересчитанные элементы появляются в массиве потому, что в этом месте происходит выбор из двух одинаковых значений.
Как это исправить - я не знаю, требуется помощь
Еще переписал программу, теперь пересчёт ведется с последнего элемента, чтобы потом проще было выводить путь
Код:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{

	const int n1 = 20, n2 = 20, n3 = 20;
	string res1 = "";
	int arr[n1][n2][n3];
	int b[n1][n2][n3];
	int min = 0;
	ifstream fin("input.txt");
	int z, y, x;		//matrices, lines, values
	fin >> z >> y >> x;

	for (int i = 0; i < z; i++) {
		for (int j = 0; j < y; j++) {
			for (int k = 0; k < x; k++) {
				fin >> arr[i][j][k];
				b[i][j][k] = arr[i][j][k];
				cout << '\t' << arr[i][j][k];
			}
			cout << endl;
		}
		cout << endl;
	}
//Заполнение строк, столбцов и матрицы, которые недостижимы
	for (int i = 0; i <= z; i++) {
		for (int j = 0; j <= y; j++) {
			for (int k = 0; k <= x; k++) {
				b[i][j][x] = INT_MAX;
				b[i][y][k] = INT_MAX;
				b[z][j][k] = INT_MAX;
			}
		}
	}

	int i1 = 0;
	int j1 = 0;
	int k1 = 0;
//Пересчёт массива с последнего элемента к нулевому
	for (int i = z - 1; i >= 0; i--) {
		for (int j = y - 1; j >= 0; j--) {
			for (int k = x - 1; k >= 0; k--) {

				if (b[i + 1][j][k] < b[i][j + 1][k] &&
					b[i + 1][j][k] < b[i][j][k + 1]) {
					b[i][j][k] = b[i + 1][j][k] + arr[i][j][k];
				}
				else if (b[i][j + 1][k] < b[i + 1][j][k] &&
					b[i][j + 1][k] < b[i][j][k + 1]) {
					b[i][j][k] = b[i][j + 1][k] + arr[i][j][k];
				}
				else if (b[i][j][k + 1] < b[i + 1][j][k] &&
					b[i][j][k + 1] < b[i][j + 1][k]) {
					b[i][j][k] = b[i][j][k + 1] + arr[i][j][k];
				}
				min = b[0][0][0];
				cout << '\t' << "(" << i << "," << j << "," << k << ")" << b[i][j][k];
			}
			cout << endl;
		}
		cout << endl;
	}
	cout << "-------------------------------------" << endl;
	for (int i = 0; i < z; i++) {
		for (int j = 0; j < y; j++) {
			for (int k = 0; k < x; k++) {
				if (i == i1 && j == j1 && k == k1) {
					res1 += "(" + to_string(i) + "," + to_string(j) + "," + to_string(k) + ") ";
					if (b[i + 1][j][k] < b[i][j + 1][k] &&
						b[i + 1][j][k] < b[i][j][k + 1]) {
						i1 = i + 1;
					}
					else if (b[i][j + 1][k] < b[i + 1][j][k] &&
						b[i][j + 1][k] < b[i][j][k + 1]) {
						j1 = j + 1;
					}
					else if (b[i][j][k + 1] < b[i + 1][j][k] &&
						b[i][j][k + 1] < b[i][j + 1][k]) {
						k1 = k + 1;
					}
				}
			}
		}
	}
	cout << "Path: " << res1 << endl;
	cout << "Length: " << min << endl;
	system("pause");
	return 0;
}
Теперь файл input.txt выглядит так:
3 4 4

1 4 8 2
3 10 5 1
7 6 4 5
8 3 18 17

5 1 8 16
4 3 11 5
8 3 10 14
3 20 20 8

14 4 23 3
13 8 10 8
19 16 15 29
1 17 10 6
Останавливается на элементе (0, 1, 3), так как там идет выбор между двумя равными значениями. Как это исправить? Нужна помощь
xNos вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Динамическое программирование Daniiil Visual C++ 6 10.01.2016 12:48
Динамическое программирование. IllidanStormrage Помощь студентам 0 06.11.2011 19:03
динамическое программирование stefan0202 Паскаль, Turbo Pascal, PascalABC.NET 3 07.02.2011 22:05
Динамическое программирование Daniya.ru Общие вопросы .NET 2 19.12.2010 11:40
Динамическое программирование. MAKEDON Помощь студентам 6 26.08.2009 14:10