• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Warstwy maksimów w zbiorze punktów

0 głosów
1,066 wizyt
pytanie zadane 29 maja 2018 w C i C++ przez Korvix Nowicjusz (170 p.)
edycja 29 maja 2018 przez Korvix

Punkt p płaszczyzny dominuje nad punktem q jeżeli obydwie współrzędne są większe od odpowiednich współrzędnych q: (px>qx) && py>qy). Punkt należący do pewnego zbioru jest punktem maksymalnym tego zbioru, jeżeli żaden inny punkt zbioru nie dominuje nad p.  Opracować program, który pobiera z wejścia standardowego, lub generuje losowo, zbiór punktów o współrzędnych całkowitych i dla każdego punktu wyznacza numer warstwy maksymalnej, do której ten punkt należy. Punkt należy do warstwy 1, jeżeli jest maksymalny w zbiorze; do warstwy 2, jeżeli jest maksymalny po usunięciu warstwy 1; itd. Dla małych konfiguracji program powinien umożliwiać prezentację pseudograficzną (znakową).

Dostałem takie zadanie do zrobienia i mam problem jak zrobić szukanie warstw maksymalnych. Nie mogę wymyślić jak to powinno być zrobione żeby:

  1. Posortować punkty do kolejnych warstw
  2. Zrobić układ współrzędnych z 4 ćwiartkami i zaznaczonymi na nim punktami bez rozjechania się całości

Wklejam co na tą chwilę udało mi się osiągnąć i bardzo proszę o pomoc.

#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;

void Pseudograf(vector<pair<int, int> >& Punkty, int ile)
{
	cout << endl << endl;
	int MAX = 10;
	for (int y = MAX; y >= -MAX; y--)
	{
		cout << y % 10 << ": ";
		for (int x = -MAX; x <= MAX; x++)
		{
			for (int i = 0; i < ile; i++)
			{
				if (Punkty[i].first == x && Punkty[i].second == y)
				{
					cout << "o ";
				}
			}
			cout << ". ";
		}
		cout << endl;
	}
	cout << "   ";
	for (int x = -MAX; x < MAX; ++x)
	{
		cout << x % 10 << ' ';
	}
	cout << endl << endl;
}

void Sortowanie(vector<pair<int, int> >& Punkty, int ile)
{
	vector<pair<int, int> > Tymczasowy;
	sort(Punkty.begin(), Punkty.end());
	cout << endl << endl;
	for (int i = ile-1; i >= 0; i--)
	{
		Tymczasowy.push_back(make_pair(Punkty[i].first, Punkty[i].second));
	}
	Punkty.clear();
	for (int i = 0; i < ile; i++)
	{
		Punkty.push_back(make_pair(Tymczasowy[i].first, Tymczasowy[i].second));
		cout << "Punkt " << i + 1 << ": ";
		cout << Punkty[i].first << " " << Punkty[i].second << endl;
	}
}

int main()
{
	vector<pair<int, int> > Punkty;
	int ile, zakres_od, zakres_do, wartosc_x, wartosc_y;
	srand(time(NULL));

	int m = 0;
	while (m > 3 || m < 1)
	{
		Punkty.clear();
		system("cls");
		cout << "********************MENU********************" << endl;
		cout << "1. Wprowadzanie danych z konsoli" << endl;
		cout << "2. Wprowadzanie danych losowych" << endl;
		cout << "3. Wyjscie z programu" << endl;
		cout << "********************************************" << endl;
		cout << "Wybieram: " << endl;
		cin >> m;
		system("cls");
		switch (m)
		{
		case 1:
			cout << "Podaj ilosc punktow do wprowadzenia" << endl;
			cin >> ile;
			for (int i = 0; i < ile; i++)
			{
				cout << "x:";
				cin >>wartosc_x;
				cout << "y:";
				cin >> wartosc_y;
				Punkty.push_back(make_pair(wartosc_x, wartosc_y));
			}
			cout << endl << endl;
			for (int i = 0; i < ile; i++)
			{
				cout << "Punkt " << i + 1 << ": ";
				cout << Punkty[i].first << " " << Punkty[i].second << endl;
			}
			Sortowanie(Punkty, ile);
			cout << endl << "Aby wrocic do MENU wpisz 0" << endl << "Aby wyjsc wpisz 3" << endl;
			cin >> m;
			break;
		case 2:
			cout << "Podaj ilosc punktow do wygenerowania" << endl;
			cin >> ile;
			cout << endl << "Podaj zakres" << endl;
			cout << "OD:";
			cin >> zakres_od;
			cout << "DO:";
			cin >> zakres_do;
			for (int i = 0; i < ile; i++)
			{
				wartosc_x = ((rand() % (zakres_do - zakres_od + 1)) + zakres_od);
				wartosc_y = ((rand() % (zakres_do - zakres_od + 1)) + zakres_od);
				Punkty.push_back(make_pair(wartosc_x, wartosc_y));
			}
			cout << endl << endl;
			for (int i = 0; i < ile; i++)
			{
				cout << "Punkt " << i + 1 << ": ";
				cout << Punkty[i].first << " " << Punkty[i].second << endl;
			}
			Sortowanie(Punkty, ile);
			Pseudograf(Punkty, ile);
			cout << endl << "Aby wrocic do MENU wpisz 0" << endl << "Aby wyjsc wpisz 3" << endl;
			cin >> m;
			break;
		case 3:
			exit(0);
			break;
		}
	}
}

 

komentarz 1 czerwca 2018 przez RafalS VIP (122,780 p.)
dalej potrzebujesz?
komentarz 1 czerwca 2018 przez Korvix Nowicjusz (170 p.)
Tak, na poniedziałek mam do oddania :/
komentarz 1 czerwca 2018 przez RafalS VIP (122,780 p.)
jutro to ogarne, nie brzmi trudno

2 odpowiedzi

+1 głos
odpowiedź 2 czerwca 2018 przez RafalS VIP (122,780 p.)
edycja 3 czerwca 2018 przez RafalS
 
Najlepsza

Najpierw krytyka kodu, żebyś się czegoś nauczył.

Czemu się rozjeżdza?

            for (int i = 0; i < ile; i++)
            {
                if (Punkty[i].first == x && Punkty[i].second == y)
                {
                    cout << "o ";
                }
            }
            cout << ". ";

niezależnie od tego czy w danej linii zaznaczyłeś punkt i tak potem stawiasz kropke. Można to załatwić flagą czyNarysowanoPunkt, ale trzeba pamiętać o wyeliminowaniu rysowania kilku o przez kilka punktów w tym samym miejscu.

Co do samego rozjeżdzania to można użyć z nagłowka <iomanip>

cout << setw(3) << y << ":";

wtedy szerokość wypisana będzie stała.

sort(Punkty.begin(), Punkty.end());

Nie wiem czy wiesz co domyślnie robi sort dla pary - porównuje firsty, jesli równe to second. Możliwe, że to chciałes osiągnąć, bo ja np nie ograniam po co tu coś sortować. 

	for (int i = ile - 1; i >= 0; i--)
	{
		Tymczasowy.push_back(make_pair(Punkty[i].first, Punkty[i].second));
	}
	Punkty.clear();
	for (int i = 0; i < ile; i++)
	{
		Punkty.push_back(make_pair(Tymczasowy[i].first, Tymczasowy[i].second));
		cout << "Punkt " << i + 1 << ": ";
		cout << Punkty[i].first << " " << Punkty[i].second << endl;
	}

Odwracasz posortowany vector i przepisujesz spowrotem do oryginalnego. Ale wiesz, że jest coś takiego jak std::reverse(Punkty.begin(), Punkty.end())? I jest też coś takiego jak konstruktor kopiujący wektora, nie musisz tego robić ręcznie, jeśli nie chcemy tworzyć nowego vectora to można też wypełnić go jedną metodą:

Punkty.insert(Punkty.end(), Tymczasowy.begin(), Tymczasowy.end());
void Pseudograf(vector<pair<int, int> >& Punkty, int ile)

vector ma metode size :P, nie musisz przesyłać długości.

Co do rozwiąznia problemu - co za dziwnie postawiony problem :P. Kminiłem sporo nad tym aż wymyśliłem. Trzeba zrobić dokładnie to co jest napisane w poleceniu xD. Czyli dopóki jest jeszcze jakiś punkt w zbiorze to szukasz punktów bezwględnie maksymalnych, czyli takich nad którymi żaden inny punkt nie dominuje. Gdy znajdziesz te punkty to masz jedną warstwę. Wywalasz je więc ze zbioru punktów i powtarzasz rozumowanie. Oczywiście napisałem to, żeby sprawdzić czy działa. Dodałem komentarze, have fun:

struct Punkt {
    int x, y;
    //przeciazenie operatora, dla wlasnej wygody
    //implementuje definicje dominacji z zadania
    bool operator>(const Punkt& p2) const {
        return x > p2.x && y > p2.y;
    }
    //funkcja std::remove, ktorej bedziemy uzywac wymaga
    //zeby obiekty dalo sie do siebie przyrownac
    bool operator==(const Punkt& p2) const {
        return x == p2.x && y == p2.y;
    }
};
//zeby dalo sie wypisywac bezposrednio cout<<punkt;
std::ostream& operator<<(std::ostream& out, const Punkt& p) {
    return out << "[" << p.x << "," << p.y << "]";
}

int main() {
    vector<Punkt> Punkty = {
        { 1,1 },{ 1,1 },{ 1,2 },{ 5,3 },{ 3,5 },{ 10,10 },{ 2,6 } };
    //tworze zbior roboczy - kopie punktow, bo bedziemy potrzebowali usuwac punkty
    vector<Punkt> ZbiorRoboczy(Punkty);
    //flaga, ktora mowi czy dany punkt jest maksymalny w obecnym zbiorze
    bool maksymalny = true;
    //warstwy rozumiane w ten sposob, ze Warstwy[i] to wektor punktow
    //nalezacych do i-tej warstwy
    vector<vector<Punkt>> Warstwy;
    //sprawdzamy czy zbior roboczy nie jest juz pusty
    //w tej petli bedziemy tworzyc kolejne warstwy
    for (int warstwa = 0; ZbiorRoboczy.size() > 0; warstwa++)
    {
        //iniciujemy warstwe pustym wektorem punktow
        Warstwy.push_back(vector<Punkt>());
        //dla kazdego punktu sprawdzamy czy dominuje on nad wszystkimi innymi
        //dla kazdego punktu porownujemy go z cala reszta
        //jesli ktorykolwiek bedzie nad nim dominowal to przerywamy
        for (int i = 0; i < ZbiorRoboczy.size(); i++) {
            maksymalny = true;
            for (int j = 0; j < ZbiorRoboczy.size(); j++) {
                if (i != j && ZbiorRoboczy[j] > ZbiorRoboczy[i]) {
                    maksymalny = false;
                    break;
                }
            }
            if (maksymalny)
                Warstwy[warstwa].push_back(ZbiorRoboczy[i]);
        }
        //usuwamy punkty dodane do warstwy ze zbioru roboczego (tresc zadania)
        for (auto p : Warstwy[warstwa]) {
            //skopiowane z stackoverflow "how to remove element by value from vector"
            ZbiorRoboczy.erase(std::remove(ZbiorRoboczy.begin(), ZbiorRoboczy.end(), p), ZbiorRoboczy.end());
        }
    }

    //wypisujemy warstwy
    for (auto& warstwa : Warstwy) {
        for (auto& punkt : warstwa) {
            cout << punkt << "  ";
        }
        cout << endl;
    }
}

Pasowałby to porozdzielać na funkcje, ale jest późno i już mi się nie chce :P

Wydaje mi się, że to działa. Jak czegoś nie rozumiesz to pytaj. Przeciążanie operatorów dla swojej własnej wygody i jeden do funkcji std::remove, ale z pewnością da się wywalić element z vectora bez użycia przeciążania operatorów,  jeśli tego nie ogarniasz.

komentarz 3 czerwca 2018 przez RafalS VIP (122,780 p.)
up - rozwiązałem problem
komentarz 3 czerwca 2018 przez Korvix Nowicjusz (170 p.)

Dziękuje Ci bardzo uratowałeś mi tyłek laugh

komentarz 3 czerwca 2018 przez Korvix Nowicjusz (170 p.)

A z czego korzystałeś pisząc ten program? Bo w Visual Studio 2017 wywala mi mnóstwo błędów frown

komentarz 3 czerwca 2018 przez RafalS VIP (122,780 p.)
Haha, z visual studio 2017 :D. Błąd jest bo wkleiłem dwa razy definicje struktury Punkt. Już poprawiam
komentarz 3 czerwca 2018 przez Korvix Nowicjusz (170 p.)

Chyba ta wersja liczy to najlepiej bo w pozostałych przypadkach z tymi danymi liczy tylko do 3 warstwy. Co odpowiada za wstawianie a? Domyślam się że to miały być nr warstw ale nie mogę zlokalizować co to wstawia.

komentarz 3 czerwca 2018 przez RafalS VIP (122,780 p.)
Zobacz sobie jak jest wyposywane. Pewnie przez kopiowanie ze strony wrzucilo jakies śmieci do "   " wstaw tam spacje.
0 głosów
odpowiedź 3 czerwca 2018 przez RafalS VIP (122,780 p.)

Wpadłem na pomysł jak to zoptymalizować:

struct Punkt {
	Punkt(int x, int y) { this->x = x; this->y = y; }
	int x, y, warstwa = -1;
	//przeciazenie operatora, dla wlasnej wygody
	//implementuje definicje dominacji z zadania
	//wtedy da sie sprawdzic punkt1 > punkt2
	bool operator>(const Punkt& p2) const {
		return x > p2.x && y > p2.y;
	}
};

//zeby dalo sie wypisywac bezposrednio cout<<punkt;
std::ostream& operator<<(std::ostream& out, const Punkt& p) {
	return out << "[" << p.x << "," << p.y << "]: " << p.warstwa;
}
int main() {
	vector<Punkt> Punkty = {
		{ 1,1 },{ 1,1 },{ 1,2 },{ 5,3 },{ 3,5 },{ 10,10 },{ 2,6 } };

	//sortuje punkty tak, ze najbardziej dominujacy jest z przodu
	sort(Punkty.begin(), Punkty.end(), [](const Punkt& p1, const Punkt& p2) {
		return p1 > p2;
	});
	int warstwa = 1;
	//ustawiam warstwe pierwszego punktu o ile sa jakiekolwiek punkty
	if (Punkty.size() > 0)
		Punkty[0].warstwa = warstwa;
	for (int i = 0; i < Punkty.size() - 1; i++) {
		if (Punkty[i] > Punkty[i + 1])
			Punkty[i + 1].warstwa = ++warstwa;
		else Punkty[i + 1].warstwa = warstwa;
	}
	for (auto p : Punkty) 
		cout << p <<": "<< p.warstwa<<endl;
	return 0;
}

Wybieraj którą wersje wolisz. Przed optymalizacją jest niby pewniejsza, bo lecimy z definicji zadania, ale wydaje mi sie, że sa równoważne.

komentarz 3 czerwca 2018 przez RafalS VIP (122,780 p.)

xD jeszcze uproszczona wersja gdybyś czegoś nie rozumiał :P:

struct Punkt {
	Punkt(int x, int y) { this->x = x; this->y = y; }
	int x, y, warstwa = -1;
};

bool porownanieDwochPunktow(const Punkt& p1, const Punkt& p2) {
	return p1.x > p2.x && p1.y > p2.y;
}
int main(){
	vector<Punkt> Punkty = {
		{ 1,1 },{ 1,1 },{ 1,2 },{ 5,3 },{ 3,5 },{ 10,10 },{ 2,6 } };

	//sortuje punkty tak, ze najbardziej dominujacy jest z przodu
	sort(Punkty.begin(), Punkty.end(), porownanieDwochPunktow);
	int warstwa = 1;
	//ustawiam warstwe pierwszego punktu o ile sa jakiekolwiek punkty
	if (Punkty.size() > 0)
		Punkty[0].warstwa = warstwa;
	for (int i = 0; i < Punkty.size() - 1; i++) {
		if (Punkty[i].x > Punkty[i + 1].x && Punkty[i].y > Punkty[i+1].y)
			Punkty[i + 1].warstwa = ++warstwa;
		else Punkty[i + 1].warstwa = warstwa;
	}
	for (auto p : Punkty)
		cout << "[" << p.x << "," << p.y << "]: " << p.warstwa << endl;
	return 0;
}

 

Podobne pytania

0 głosów
2 odpowiedzi 1,524 wizyt
pytanie zadane 24 stycznia 2019 w HTML i CSS przez ziomek7 Obywatel (1,060 p.)
0 głosów
1 odpowiedź 1,102 wizyt
pytanie zadane 23 sierpnia 2018 w HTML i CSS przez FutrzaQQ Nowicjusz (180 p.)
0 głosów
1 odpowiedź 480 wizyt

93,742 zapytań

142,678 odpowiedzi

323,297 komentarzy

63,328 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...