• 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

Object Storage Arubacloud
0 głosów
387 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,820 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,820 p.)
jutro to ogarne, nie brzmi trudno

2 odpowiedzi

+1 głos
odpowiedź 2 czerwca 2018 przez RafalS VIP (122,820 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,820 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,820 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,820 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,820 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,820 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 821 wizyt
pytanie zadane 24 stycznia 2019 w HTML i CSS przez ziomek7 Obywatel (1,060 p.)
0 głosów
1 odpowiedź 623 wizyt
pytanie zadane 23 sierpnia 2018 w HTML i CSS przez FutrzaQQ Nowicjusz (180 p.)
0 głosów
1 odpowiedź 248 wizyt

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

61,960 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.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...