Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > Java
You last visited: Today at 07:12

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Exhaustive Search

Discussion on Exhaustive Search within the Java forum part of the Coders Den category.

Reply
 
Old   #1
 
The_Dentist's Avatar
 
elite*gold: 13
Join Date: Nov 2014
Posts: 71
Received Thanks: 4
Exhaustive Search

Hallo,

Ich soll folgendes implementieren, allerdings habe ich derzeit keine Ahnung wie ich da am besten anfange.

Gegeben ist ein 2 Dimensionales Boolean Array.

z.B. sowas: (In unserem Bsp. sind das Lehrer und Fächer)

boolean[][] Abgedeckt=
{
{true, true, false},
{false, true, false},
{true, false, true},
};

z.B.
Gesucht ist nun die kleinste Zahl an Lehrern, sodass alle Fächer abgedeckt sind.

Das Ganze soll rekursiv geschehen.

Ich habe Probleme die Abbruchbedingung und Parameter für die Rekursion zu finden. Also einerseits muss ich logischerweise, immer auf das Array zu greifen können. Aber wie finde ich raus, ob das die kleinste Zahl ist. Speicher ich mir alle Möglichkeiten?

MfG
The_Dentist is offline  
Old 06/21/2015, 14:21   #2
 
Shadow992's Avatar
 
elite*gold: 77
Join Date: May 2008
Posts: 5,430
Received Thanks: 5,878
Einfach das maximum + index speichern (Pseudo-Code):

Code:
Funktion solve(int i)
{
  if(i==abgedeckt.size())
    return;
  int maxAbgedeckt=0;
  int maxIndex=-1;
  int tmpAbgedeckt=0;
  For j=0; j<abgedeckt[i].length; j++
  {
    if(Abgedeckt[i][j]==true)
      tmpAbgedeckt++;
  }
  if(tmpAbgedeckt>maxAbgedeckt)
  {
    maxAbgedeckt=tmpAbgedeckt;
    maxIndex=i;
  }
  solve(i+1);
}
Auch wenn ich es ziemlich sinnlos finde das Rekursiv zu lösen, weil das viel schöner mit 2 For-Schleifen läuft.

Alternativ kannst du auch statt es in einer globalen/Klassen globalen variable zu speichern den Index/das Maximum per Referenz übergeben oder returnen lassen o.ä.

Edit:
Ich sehe es war nach dem Minimum gefragt, aber das läuft logischerweise analog ab.

Edit2:
Möglicherweise habe ich die Aufgabe falsch verstanden.
Geht es darum das Minimum der gesetzten true variablen im array zu finden oder geht es darum, dass man die verschiedenen Array-Einträge so kombiniert, dass am Ende ein neues eindimensionales Array entsteht, welches die Größe von der 2. Dimension des Ausgangsarrays besitzt und überall "true" stehen hat?
Shadow992 is offline  
Thanks
1 User
Old 06/21/2015, 14:48   #3
 
The_Dentist's Avatar
 
elite*gold: 13
Join Date: Nov 2014
Posts: 71
Received Thanks: 4
Also Ihr müsst Euch das wie folgt vorstellen, wir haben eine Tabelle:

Fach0 Fach1 Fach2
Lehrer 0   
Lehrer 1   
Lehrer 2   

Und jetzt geht es darum, mit möglichst wenigen Lehrern alle Fächer abzudecken. Das Array füllt quasi diese Tabelle aus.
The_Dentist is offline  
Old 06/21/2015, 15:16   #4
 
Shadow992's Avatar
 
elite*gold: 77
Join Date: May 2008
Posts: 5,430
Received Thanks: 5,878
Alles klar, ich habe mich eben an eine sehr einfache Rekursive Backtracking-Lösung gesetzt. Die Lösung ist wirklich enorm schlecht was Laufzeit angeht, aber ich wollte nicht unnötig das Ganze verkomplizieren, es geht ja nur darum, dass du das Prinzip verstehst.

Ich habe den Code zwar eben schnell in C/C++ hingeschrieben, habe aber versucht nur Elemente zu benutzen die es genau so (mit leicht anderer Syntax) in Java und C/C++ gibt.

Meine Lösung (ist getestet und sollte klappen):
PHP Code:
#include <iostream>

int cPossibleCoverage=3;
int cToCover=4;
bool possibleCoverage[3][4]=
{
    {
truetruefalse,false},
    {
falsetruefalse,false},
    {
truefalsetrue,true}
};

bool setsUsed[3];
bool bestSetsUsed[3];
int currentMin=1000000000;

bool isValidSolution()
{
    
int tmpCovered[4]={false,false,false,false};

    for(
int i=0;i<cPossibleCoverage;i++)
    {
        if(
setsUsed[i]==true)
        {
            for(
int j=0;j<cToCover;j++)
            {
                if(
possibleCoverage[i][j]==true)
                {
                    
tmpCovered[j]=true;
                }
            }
        }
    }

    for(
int j=0;j<cToCover;j++)
    {
        if(
tmpCovered[j]==false)
        {
            return 
false;
        }
    }
    return 
true;
}

void solveCoverageProblem(int idxCoveragebool add)
{
    if(
idxCoverage==cPossibleCoverage)
    {
        if(
isValidSolution()==true)
        {
            
int tmpMin=0;
            for(
int i=0;i<cPossibleCoverage;i++)
            {
                if(
setsUsed[i]==true)
                {
                    
tmpMin++;
                }
            }

            if(
currentMin>tmpMin)
            {
                
currentMin=tmpMin;
                for(
int i=0;i<cPossibleCoverage;i++)
                {
                    
bestSetsUsed[i]=setsUsed[i];
                }
            }
        }
        return;
    }

    if(
add==true)
    {
        
setsUsed[idxCoverage]=true;
    }
    else
    {
        
setsUsed[idxCoverage]=false;
    }

    
solveCoverageProblem(idxCoverage+1,true);
    
solveCoverageProblem(idxCoverage+1,false);
}

int main()
{
    
solveCoverageProblem(0,true);
    
solveCoverageProblem(0,false);

    
// print minimum count sets used (currentMin)
    
std::cout<<currentMin<<std::endl;
    for(
int i=0;i<cPossibleCoverage;i++)
        
std::cout<<"["<< <<"]: "<<bestSetsUsed[i]<<std::endl;

    return 
0;

Shadow992 is offline  
Thanks
2 Users
Old 06/21/2015, 15:48   #5
 
The_Dentist's Avatar
 
elite*gold: 13
Join Date: Nov 2014
Posts: 71
Received Thanks: 4
Ui, vielen DANK!

Gruß

€dit:

PHP Code:
if(add==true)
    {
        
setsUsed[idxCoverage]=true;
    }
    else
    {
        
setsUsed[idxCoverage]=false;
    }

    
solveCoverageProblem(idxCoverage+1,true);
    
solveCoverageProblem(idxCoverage+1,false); 
Diesen Part verstehe ich noch nicht ganz, wieso muss ich die Methode zwei mal aufrufen mit dem gleichen Index aber einmal mit true und einmal mit false?
The_Dentist is offline  
Old 06/21/2015, 18:21   #6
 
Shadow992's Avatar
 
elite*gold: 77
Join Date: May 2008
Posts: 5,430
Received Thanks: 5,878
Quote:
Originally Posted by The_Dentist View Post
Ui, vielen DANK!

Gruß

€dit:

PHP Code:
if(add==true)
    {
        
setsUsed[idxCoverage]=true;
    }
    else
    {
        
setsUsed[idxCoverage]=false;
    }

    
solveCoverageProblem(idxCoverage+1,true);
    
solveCoverageProblem(idxCoverage+1,false); 
Diesen Part verstehe ich noch nicht ganz, wieso muss ich die Methode zwei mal aufrufen mit dem gleichen Index aber einmal mit true und einmal mit false?
Die Idee des ganzen Algorithmuses sieht wie folgt aus:

Generiere jede mögliche Menge an Belegungen um alle Fächer zu überdecken, wenn man das also einmal für unsere Beispiel mit 3 Lehrern durchgeht probiert der Algorithmus das in folgender Art und Weise (in genaue dieser Reihenfolge):

als erstes wird die Lösung generiert bei der wir alle Lehrer benutzen, also die erste Lösung, die wir zwischen speichern ist:
Lehrer1 & Lehrer2 & Lehrer3

Als nächstes schauen wir die Lösung für Lehrer1 und Lehrer2 aber NICHT Lehrer3 an, also:
Lehrer1 & Lehrer2 & NICHT Lehrer3

Was nichts anderes ist als:
Lehrer1 & Lehrer2

Anschließend gehen wir (dank dem Backtracking-Verfahren) einen Schritt zurück.
Wir haben jetzt alle möglichen Lösungen dafür aufgestellt, dass Lehrer1 und Lehrer2 sicher genommen werden, aber wir wissen nicht ob Lehrer2 wirklich benötigt wird, also generieren wir als nächstes alle Lösungen wenn Lehrer2 nicht genommen wird, Lehrer1 also schon.

Dann hätten wir:
1. Lehrer1 & NICHT Lehrer2 & Lehrer3
2. Lehrer1 & NICHT Lehrer2 & NICHT Lehrer3

Jetzt sind wir aber davon ausgegangen, dass wir Lehrer1 sicher brauchen, also müssen wir auch noch alle Fälle betrachten, wo wir Lehrer1 nicht brauchen, was dann so aussähe:

1. NICHT Lehrer1 & Lehrer2 & Lehrer3
2. NICHT Lehrer1 & Lehrer2 & NICHT Lehrer3
3. NICHT Lehrer1 & NICHT Lehrer2 & Lehrer3
4. NICHT Lehrer1 & NICHT Lehrer2 & NICHT Lehrer3

Damit haben wir alle möglichen Kombinationen angeschaut, die es gibt und jetzt müssen wir uns nur während dem Anschauen merken welche Lösung am wenigstens Lehrer benötigt hat.

Nun zurück zur eigentlichen Frage:
"Wieso brauchen wir 2 Aufrufe?"
Die Antwort darauf muss man in 2 Teilen beantworten:

Teil 1:
Nicht jeder Algorithmus, der rekursiv arbeitet und das Problem löst benötigt 2 verschiedene Aufrufe. Es unterlag jetzt also meiner Willkür den Algorithmus so zu gestalten, dass wir 2 Aufrufe benutzen. Mein Hauptargument es so zu machen lag besonders bei der Kürze des Codes der entsteht, da ich das nur "schnell" zusammen schreiben wollte.
Laufzeit technisch ist mein Code eh eine Katastrophe (wie bereits angedeutet)

Teil 2:
Was genau machen die 2 Aufrufe jetzt genau?
Da wir, wie oben beschrieben, zuerst davon ausgehen dass wir alle Lehrer brauchen und dann schrittweise auch die Möglichkeiten durchgehen, wo wir nicht alle Lehrer brauchen bietet es sich an folgendes Vorgehen zu benutzen:

Gehe alle Lehrer durch und pro Lehrer gibt es 2 "neue" Pfade, die man verfolgen kann, um eine Lösung zu finden.
Einmal den Pfad: Der Lehrer ist Teil der Lösung und
den Pfad: Der Lehrer ist nicht Teil der Lösung

Daher auch die 2 Aufrufe, einmal verfolgen wir den Pfad weiter, wenn der Lehrer Teil der Lösung ist ( solveCoverageProblem(idxCoverage+1,true); ) und einmal wenn er nicht Teil der Lösung ist ( solveCoverageProblem(idxCoverage+1,false); )

Dementsprechend speichern wir in unserem bool Array dann auch false (der Lehrer gehört nicht zur aktuellen Lösung) bzw. true (der Lehrer gehört zur aktuellen Lösung).

Edit:
Wenn dus trotzdem nicht verstehst sag Bescheid, dann versuch ich dir das Ganze graphisch klar zu machen.
Shadow992 is offline  
Thanks
2 Users
Reply




All times are GMT +1. The time now is 07:12.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.