Kombinatorik: elemanları kriteri kalırken 100 elemanlarının 10 grupları oluşturmak

2 Cevap php

Ben kombiçiçindedeatveyaik ile ilgili bir sveyaunumuz var. Ben bir hikaye olarak anlatmaya çalışacağım ne yazık ki, ben soyut tarif edemez. :)

Problem:

  1. Okul 100 çocuk var.
  2. They all have unique heights, assumiçiçindedeg the values vardır 100-199cm.
  3. You want to build 10 groups, each consistiçiçindedeg of 1-99 children.
  4. Çocukların boy sıralanması gerekir iken nasıl tüm gruplar içindeşa edebilirsiçindeiz?
  5. I need all possible solutions fveya these groups siçiçindedece it isn't hard to fiçiçindeded one constellation.

Shveyat ve easy:

Tüm 100 çocuk yan yana durmak. Sen sadece gruplar haliçiçindedede onları bölmek ve bunun içiçiçindede tüm çözümler bulmak içiçiçindede nerede karar vermek zveyaunda.

Example (values vardır the heights):

[120 ... 190 ... 199] ... [126 ... 137 ... 144 ... 188] is not possible

[101] ... [104 ... 105 ... 112 ... 149] ... [169 ... 189] is possible

Bana yardımcı olur umarım. Şimdiden çok teşekkür ederiz!

PS: Bu bir ödev var. ;) Nveyamalde, ben numaraları ile yapar bir işlev gerekir. Ama soyut "Tüm numaralar sıralanır iken sayılar k grupları biçiçindedea" gibi bu tarif olamazdı. Ben bunu bu şekilde anlamak düşündüm. :) PHP bir çözüm iyi olurdu ama ben de diğer dillerde çözümleri görmek içiçiçindede memnun olacaktır. :)

2 Cevap

Anladığım kadarıyla, size etkili numaraları x bulmak istiyorsanız, 10 bölüme aralığını [100.199] bölümleme yollarını yani soran [0], ..., x [10] öyle ki:

x[0] = 100 < x[1] < x[2] < ... < x[9] < x[10] = 199

Belirli bir aralığını bölümlemek için yollar sayar bir özyinelemeli işlev partition(intervalSize, pieces) tanımlayın. Eğer sonra partition(100, 10).

Aşağıdaki Java kodu bölümleri sayar (üzgünüm, PHP biliyorsanız o kadar iyi değil):

public class Partitions
{
    static long[][] partitions = new long[100][10];

    private static long partition(int intervalSize, int pieces)
    {
    	if (partitions[intervalSize-1][pieces-1] != 0) {
    		return partitions[intervalSize-1][pieces-1];
    	}
    	long partition = 0L;
    	if (pieces == 1) {
    		partition = 1L;
    	} else {
    		for (int i = 1; i <= intervalSize - 1; i++) {
    			partition += partition(intervalSize - i, pieces - 1);
    		}
    	}
    	partitions[intervalSize-1][pieces-1] = partition;
    	return partition;
    }

    public static void main(String[] args)
    {
    	System.out.println(partition(100, 10));		
    }

}

Aşağıdaki Java kodu gerçek bölümleri yazdırır. Bölüm sayısı (100,10) için çok yüksek olduğu için, I (5,3) için cevabı gösteren kulüpler:

public class Partitions2
{
    private static void showPartitions(int sizeSet, int numPartitions)
    {
    	showPartitions("", 0, sizeSet, numPartitions);
    }

    private static void showPartitions(String prefix, int start, int finish,
    		int numLeft)
    {
    	if (numLeft == 0 && start == finish) {
    		System.out.println(prefix);
    	} else {
    		prefix += "|";
    		for (int i = start + 1; i <= finish; i++) {
    			prefix += i + ",";
    			showPartitions(prefix, i, finish, numLeft - 1);
    		}
    	}
    }

    public static void main(String[] args)
    {
    	showPartitions(5, 3);
    }
}

Çıktısı:

|1,|2,|3,4,5,
|1,|2,3,|4,5,
|1,|2,3,4,|5,
|1,2,|3,|4,5,
|1,2,|3,4,|5,
|1,2,3,|4,|5,

I need all possible solutions for these groups since it isn't hard to find one constellation.

Normalde, orada 100! 100 öğeleri permute için, ancak düzeni korumak konum beri, senin sorunun boyutu aşağı düşürebilir yolları substantially. Ne açıklayan bir integer partitioning problem olduğunu. Örneğin, 5'e kadar eklemek mümkün olan tüm tamsayı alt halinde 5 sayısını bölümleme edildi diyelim, olsun istiyorum {5}, {4, 1}, {3, 2}, {3, 1, setleri 1 ,}, {2, 2, 1}, {2, 1, 1, 1}, {1, 1, 1, 1, 1}.

Tamsayı bölüm sayısı tamsayı büyüklüğü ile katlanarak büyür, ancak 190.569.292 tanesi vardır beri üstel büyüme, sen n = 100 tüm bölümler aracılığıyla numaralandırabilir yeterince yavaş. Burada ek kısıtlama bir Ferrer diyagramı kullanılarak numaralandırmak için kolay tam 10 öğeleri içeren setleri için, tüm bölümleri süzmek istediğiniz olmasıdır.

Aşağıdaki gibi bir 20 col x 3 sıra ızgara ile başlar: I 3 kova içine sayı 20 bölüm tarafından bir Ferrer diyagramı gösterebilen:

 12345678901234567890
1******************
2*
3*

Yani, ilk bölümdür {18, 1, 1}

Şimdi bir sonraki yuvaya yığının üstüne bir öğeyi taşımak:

 12345678901234567890
1*****************
2**
3*

Bizim yeni bölüm {17, 2, 1}. Biz diğer bir yığından başka bir öğe yapabilirsiniz:

 12345678901234567890
1****************
2***
3*

Şimdi var {16, 3, 1}. Tüm permütasyonlarını ({17, 1, 2} {17, 2, 1} den farklı bir bölüm olup olmadığını onun kadar) numaralandırmak bitene kadar bu şekilde devam.

Sıfırdan bu işlevi yazma meydan isterseniz, - bu noktadan itibaren, size ihtiyacınız algoritmasının genel hatlarını tasavvur etmek gerekir. Diğer insanlar zaten written lots of efficient functions kolayca sorunu çözmek için var.