Einfaches Informatikproblem

OP (Firma: Wellmann) #2198907
Lesenswert?

Wie geht man in der Informatik an folgendes Problem einfach heran:

Es ist eine Zahl gegeben, etwa 800.

Dieser will man sich nun mit möglichst wenigen vorgegebenen Zahlen durch 
Addition annähern.

Vorgegeben sind etwa 470, 330, 10, 1.

Im Beispiel also:
470 + 330 = 800 -> Zwei vorgegebene Zahlen verwendet, gut.
10 + 10 + 10 + 470 ... -> mehr als 2
330 + 10 + 10 .... -> mehr als 2
1 + 1 + 1 + 1 ... -> viel mehr als 2

Ich will also eine Liste einlesen mit vorgegebenen Zahlen.

Dann gebe ich ein 800.

Das Programm gibt mir aus -> Am besten erreichbar durch 470 + 330.
Gast #2198916
Lesenswert?

wenn es wirklich nur ein paar zahlen sind - dann brute force( einfach 
alle Kombinationen ausprobieren). Wenn es genau passt kann man ja 
abbrechen. Optimieren kann man dadurch das man erst die größte noch 
freihe Zahl verwendet.

Das ganze ist nicht weiter kompliziert, man braucht eventuell mehr code 
für das einlesen und ausgeben als für die Berechnung.
Gast #2198922
Lesenswert?

Ich habs eilig.

1. Geht um Widerstände oder?
2. Falls es Hausaufgaben sind: Machen wir nicht.
3. wenn 1==true guck mal in der Artikelsammlung, irgendwo sind da 
Programme verlinkt die genau sowas machen.
4. wenn 1==true && 2==false && 3 nichts bringt posten, der Algo ist auf 
den ersten Blick nicht schwierig.
Gast #2198924
Lesenswert?

Brute-force: Berechne alle Kombinationen, sortiere nach Anzahl Summanden 
und gib das/die Minima aus.

Da Du aber das Minimum an Summanden suchst geht es auch geschickter 
(Annahme die Summanden sind sortiert)

erster Summand == Ergebnis?
Ja, super, fertig (eventuell andere Summanden ausprobieren)
< Ergebnis : nächster Summand, s.o.
> Ergebnis : zurück zum Anfang, neuer erster Summand
OP (Firma: Wellmann) #2198956
Lesenswert?

Das Problem ist gelöst.

Um meinen Mitteilungsdrang zu befriedigen und wens interessiert: Es ging 
um Widerstände. Ein "simples" Spannungsteilerprogramm.

Beispiel:
Eingangsspannung 5,04V
Gewollte Spannung 1,4V

Ausgabe sortiert nach Abweichung:
Abweichung(Soll Ist) - R_Außen = Widerstand1 + Widerstand2 + Rest für 
R_Innen = Widerstand über dem die Spannung abgegriffen wird.

0.001657(S1.4 I1.401657) - R_Außen = 1000 + 220 + 2.000000 für R_Innen = 
470
0.001657(S1.4 I1.401657) - R_Außen = 10000 + 2200 + 20.000000 für 
R_Innen = 4700
0.001657(S1.4 I1.401657) - R_Außen = 100000 + 22000 + 200.000000 für 
R_Innen = 47000
0.001657(S1.4 I1.401657) - R_Außen = 1000000 + 220000 + 2000.000000 für 
R_Innen = 470000
0.003544(S1.4 I1.403544) - R_Außen = 470 + 100 + 2.000000 für R_Innen = 
220
0.003544(S1.4 I1.403544) - R_Außen = 4700 + 1000 + 20.000000 für R_Innen 
= 2200
0.003544(S1.4 I1.403544) - R_Außen = 47000 + 10000 + 200.000000 für 
R_Innen = 22000
0.003544(S1.4 I1.403544) - R_Außen = 470000 + 100000 + 2000.000000 für 
R_Innen = 220000
0.027762(S1.4 I1.427762) - R_Außen = 2200 + 330 + 70.000000 für R_Innen 
= 1000
0.027762(S1.4 I1.427762) - R_Außen = 220000 + 33000 + 7000.000000 für 
R_Innen = 100000
0.034535(S1.4 I1.434535) - R_Außen = 330 + 47 + 13.000000 für R_Innen = 
150
0.053846(S1.4 I1.453846) - R_Außen = 2200 + 1500 + 200.000000 für 
R_Innen = 1500
0.071858(S1.4 I1.471858) - R_Außen = 470 + 330 + 58.000000 für R_Innen = 
330
0.071858(S1.4 I1.471858) - R_Außen = 47000 + 33000 + 5800.000000 für 
R_Innen = 33000
0.073684(S1.4 I1.473684) - R_Außen = 22000 + 2200 + 1800.000000 für 
R_Innen = 10000
0.108790(S1.4 I1.508790) - R_Außen = 100 + 10 + 12.200000 für R_Innen = 
47
0.127273(S1.4 I1.527273) - R_Außen = 220 + 10 + 30.000000 für R_Innen = 
100
0.280000(S1.4 I1.680000) - R_Außen = 1 + 1 + 0.600000 für R_Innen = 1
0.280000(S1.4 I1.680000) - R_Außen = 10 + 10 + 6.000000 für R_Innen = 10
2.100000(S1.4 I3.500000) - R_Außen = 220000 + 220000 + 2160000.000000 
für R_Innen = 1000000
2.731148(S1.4 I4.131148) - R_Außen = 220000 + 220000 + 4760000.000000 
für R_Innen = 2000000
Gast #2198960
Lesenswert?

1. Sortier die Summanden nach ihrer Größe (absteigend)

2. Versuche den größten Summanden von der gesuchten Zahl abzuziehen.

Wenn kleiner Null -> nächsten Summand abziehen und Zahl natürlich so 
lassen.

Wenn größer Null und größer als der momentane Summand -> Summand 
auflisten und den Summand nochmal abziehen.

Wenn größer Null aber kleiner als der momentane Summand -> Summand 
auflisten und den nächsten ausprobieren.


Das fällt mir jetzt ganz spontan als erstes ein.
Gast #2198985
Lesenswert?

Dom schrieb:
> 1. Sortier die Summanden nach ihrer Größe (absteigend)
>
> 2. Versuche den größten Summanden von der gesuchten Zahl abzuziehen.
>
> Wenn kleiner Null -> nächsten Summand abziehen und Zahl natürlich so
> lassen.
>
> Wenn größer Null und größer als der momentane Summand -> Summand
> auflisten und den Summand nochmal abziehen.
>
> Wenn größer Null aber kleiner als der momentane Summand -> Summand
> auflisten und den nächsten ausprobieren.
>
>
> Das fällt mir jetzt ganz spontan als erstes ein.

Das ist mir auch als erstes eingefallen, die möglichen Werte sortieren 
und vom Größten her den Rest auffüllen
Aber wenn du z.B. 1000 treffen willst und hast 600 500 300 200 100 dann 
kommst du auf 600 + 300 + 100 = 1000, aber nicht auf 500 + 500 = 1000.

Insofern doch nicht ganz trivial.


Dein V. schrieb im Beitrag #2198964:
> Du sollst daraus schließen, daß es respektlos ist zu
> unterstellen es seien Hausaufgaben. Jedem gegenüber. Demjenigen
> gegenüber, bei dem es Hausaufgaben sind

Und du solltest erst mal Respekt denen gegenüber lernen, die dir helfen 
sollen.
Gast #2199008
Lesenswert?

#define MAXLIST 5

int Liste[MAXLIST] = {40, 30, 20, 10, 1}; // sortiert keine 0
int Ergebnis[MAXLIST];


// quick and dirty

void MinAdd(void)
  {
  int Quelle = 123;

  int Ziel = 0, i,j;

  for(i = 0; i < MAXLIST; i++)
    {
    do
      {
      if( (Liste[i] + Ziel) <= Quelle)
        {
        Ziel += Liste[i];
        Ergebnis[i]++;
        }
      else
        {
        break;
        }
      }while(1);
    }
  // Ausgabe
  for(i = 0; i < MAXLIST; i++)
    {
    for(j = 0; j < Ergebnis[i]; j++)
      {
      printf("%d ", Liste[i]);
      }
    }
}
Gast #2199815
Lesenswert?

Yalu X. schrieb:
> Ok, wenn hier gerade mit Fachbegriffen umhergeschmissen wird:
>
>   Dynamische Programmierung
>
> Damit lässt sich Problem sehr rechenzeit- aber nicht ganz so speicher-
> effizient lösen.

Mist das Stichwort wollte ich auch gerade in den Raum werfen :(, um 
genau dabei handelt es sich.

Standardproblem mit DP und extrem einfach wenn man immer eine 1 hat

http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=dynProg

Das erste Eingangsproblem ist genau dein Problem, linear in Zeit und 
Speicherbedarf

Und wie weiter oben schon jemand festgestllt hat, nicht alles geht 
Greedy ;)
Gast #2199945
Lesenswert?

Grotesque schrob:
>Mist das Stichwort wollte ich auch gerade in den Raum werfen :(

Wenn man Etwas in den Raum werfen will, sollte man sich überzeugen, daß
es kein Bumerang ist.

(alte australische Volksweisheit)

;-)
MfG Paul
Gast #2200417
Lesenswert?

Dein V. schrieb:
> D. I. schrieb:
>> http://www.topcoder.com/tc?module=Static&d1=tutori...
>
> Gibt es das auch in Deutsch

Nein:

aber hier mal der Code in Java
1
final int N = 1000; //maximale summe
2
int summands[] = {600,500,300,40,21,1}; //verfügbare summanden
3
int min[] = new int[N+1]; //minimale Anzahl an Summanden für Summe [0,N]
4
Arrays.fill(min, 0);
5

6
for (int i = 0; i <= N; i++)
7
{
8
  for (int j = 0; j < summands.length; j++)
9
  {
10
    if (summands[j] <= i && min[i-summands[j]]+1 < min[i])
11
    {
12
      min[i] = min[i-summands[j]] + 1;
13
    }
14
  }
15
}
16

17
System.out.printf("Fuer Summe %d brauche ich mindestens %d Summanden\n",N,summands[N]);

Den Algorithmus kann man nun so erweitern dass man sich anschließend 
rekonstruiert welche Münzen man verwendet hat

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren