LINUX.ORG.RU

Математики! откликнитесь! трабла =)


0

0

Задача:
имеется число n, задающее число откр ковычек и закр ковычек => является половиной длины строки.

нужно вывести на экран все возможные комбинации этих скобок так, чтоб каждой откр скобке соотв закр скобка
фууууууууууу два дня решить не могу
с простой перестановкой в цикле ничё не выходит
ишходник можете взять здесь (кому интересно =)) http://altnet.ru/~virus/sk.c


ну если помахать руками то вроде просто. Сперва заводишь массив int A[] и вычисляешь A[i] -- сколько субжей длины i. Ну понятно -- A[4] = A[0]*A[3] + A[1]*A[2] + A[2]*A[1] + A[3]*A[0];

Ну вычислив, заводишь сразу буфер чтобы хватило на все стринги всех длин от 1 до n.

Ну а потом "находишь" все стринги длиной 0 и 1. Все стринги длиной 2 получаешь из 0-х и 1-х. Длиной 3 -- из вычисленных ранее и т.д.

dilmah ★★★★★
()

пусть мы вставили уже m ковычек:
пусть l - колво '<', k - колво '>'
m = l + k;
f = n - m; кол-во свободных ячеек
понятно что если:
l - k == f; то вставлять на m+1 место можно только '>'
l == k; то вставлять на m+1 место можно только '<'
l > k;  то вставлять на m+1 место можно как '<' так и '>'

сухой остаток:
#include <stdlib.h>
#include <stdio.h>

char *progn;
unsigned n;

void
usage(void)
{
        fprintf(stderr, "usage: %s <n>\n", progn); 
        exit(0);
}

/*
 * Fill next character pointed by str + off
 * ob - number of '<' for a moment
 * cb - number of '<' for a moment
 */
int
filnc(char *str, unsigned ob, unsigned cb, unsigned off)
{
    char *nstr;

    if (off == n) {
        printf("%s\n", str);
        free(str);
        return 0;
    }

    nstr = (char *)malloc(n + 1);
    if (nstr == NULL) {
        fprintf(stderr, "ERR: Memory exhaused\n");
        return -1;
    }
    nstr[n] = 0;

    memcpy(nstr, str, off);
    if ((ob - cb) == (n - off)) {
        /* Only '>' can be inserted */
        nstr[off] = '>';
        filnc(nstr, ob, cb + 1, off + 1);
        return 0;
    }

    if (ob == cb) {
        /* Only '<' can be inserted */
        nstr[off] = '<';
        filnc(nstr, ob + 1, cb, off + 1);
        return 0;
    }

    if (ob > cb) {
        /* Both '<' and '<' can be inserted */

        nstr[off] = '<';
        filnc(nstr, ob + 1, cb, off + 1);
        nstr[off] = '>';
        filnc(nstr, ob, cb + 1, off + 1);
    }
    return 0;
}

int
main(int ac, char **av)
{
    char *rstr;

    progn = av[0];
    if (ac < 2)
        usage();

    n = atoi(av[1]);

    rstr = (char *)malloc(n + 1);
    if (rstr == NULL) {
        fprintf(stderr, "ERR: Memory exhaused\n");
        return -1;
    }
    rstr[n] = 0;

    filnc(rstr, 0, 0, 0);
    return 0;
}

lg ★★
()

Почему всё думают что всё так просто?
Да не просто а трудно! Вывести-то надо комбинации а не прибаление скобок к концу строки - в этом-то и вся фишка.
Во как!
ЗЫ
Выводить нада строку длиной n*2

Chek
() автор топика

Chek: почему ты думаешь что все так трудно, ведь все просто.

> Вывести-то надо комбинации
конечно все - никто не отрицает, но что это значит _все_?
понятно что первая скобка всегда будет '<' а последняя '>',
какая может быть вторая скобка?
в предыдущем моем посте подставь вместо l - 1, k - 0;
и получи что если n = 1 то поставить можно только '>' и
если n > 1 то и '<' и '>' то есть уже будет по крайней мере две ветки развития ..
далее, пусть n > 1, теперь у нас есть две строки "<<" и "<>"
и свободных ячеек (n-1)*2, что мы можем поставить на третье место в строке "<<", l = 2, k = 0
если (n-1)*2 == l - k == 2 то вставлять можно только '>', если
(n-1)*2 > l - k == 2 то вставлять можно как '>' так и '<'
допустим теперь что (n-1)*2 > 2 тогда мы имеем для строки "<<" если две строка
"<<<" и "<<>", то же самое для строки "<>" ... и так далее

> Выводить нада строку длиной n*2
это не важно .. если n = (m/2) то надо строку длиной m с учетом что m - четно

перед тобой же лежит прога .. разве она не работает?

PS: чтобы понять рекурсию сначала надо понять рекурсию.

lg ★★
()

#include <stdio.h>
int main(char *argc[], char *argv[]){
char res[256];
int x=0,j,k,n,z=0;
double i,s=1;
n=atoi(argv[1]);
for(i=0;i<n*2;i++) s*=2;
for(i=0;i<s;i++){
k=i;
for(j=0;j<(n*2);j++){
if((k%2)==0){res[j]='('; ++z;}
else{res[j]=')'; --z;}
if(z<0) x=1;
k>>=1;
}
res[n*2]='\0';
if((z==0) && (x!=1)) printf("%s\n",res);
z=0;x=0;
}
getchar();
return 0;
}
//Работает, но медленно
//n=13: 4 min 15 sec
//n=12: 60 sec
//n=11: 18 sec
//n=10: 7,5 sec
//n= 9: 4 sec
//n= 8: 1,5 sec

Susanin
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.