[완료] 알고리즘 문의드립니다..

pogusm의 이미지

01. "1111101100110001100001100000"
02. "1111011010101001010001010000"
03. "1110110110011000110000110000"
04. "1101111001100101001001001000"
05. "1011110101010100101000101000"
06. "0111110011001100011000011000"
07. "1101001111100011000101000100"
08. "1010101111010010100100100100"
09. "0110011111001010010100010100"
10. "0001111111000110001100001100"
11. "1101001000111111000011000010"
12. "1010100100111110100010100010"
13. "0110010010111110010010010010"
14. "0001110001111110001010001010"
15. "0000001111111110000110000110"
16. "1101001000100001111111000001"
17. "1010100100010001111110100001"
18. "0110010010001001111110010001"
19. "0001110001000101111110001001"
20. "0000001111000011111110000101"
21. "0000000000111111111110000011"
22. "1101001000100001000001111111"
23. "1010100100010000100001111111"
24. "0110010010001000010001111111"
25. "0001110001000100001001111111"
26. "0000001111000010000101111111"
27. "0000000000111110000011111111"
28. "0000000000000001111111111111"

임의의 패턴에 따라 0과1이 배치된 28개의 데이터가 28줄 있습니다.
(단, 각 줄마다 1은 13개, 0은 15개로 구성되어 있습니다.)

위의 총 28줄에서 몇줄을 추출하여 OR 연산을 해서
"1111111111111111111111111111" 이 되게끔 하려고 합니다.

28줄을 전부 OR 연산해버려도 되겠지만,
[최소한의 줄]을 추출하여 원하는 값을 얻고자 합니다.

예를들어 1번,6번,15번,16번 을 추출하여 OR 연산을 하면 "11111..." 값이 나옵니다.
01. "1111101100110001100001100000"
06. "0111110011001100011000011000"
15. "0000001111111110000110000110"
16. "1101001000100001111111000001"
------------------------------------
합. "1111111111111111111111111111"

28*28을 예로 들었지만, 84*84, 210*210, .... 5005*5005 같이 큰 데이터에서도 적용 가능한 알고리즘을 찾고 싶습니다.

좋은 아이디어 있으면 좀 나눠주세요 ㅠㅠㅠ

semmal의 이미지

가능한 조합이 반드시 하나이상 존재하는가요? 즉, 없을 수도 있나요?

가장 적은 조합만 찾으면 되는 건가요? 아니면 모든 조합을 다 찾아야 하는 건가요?

------------------------------
How many legs does a dog have?

pogusm의 이미지

가능한 조합은 여러개가 존재할 수 있습니다. (없을수는 없습니다)
하지만 단 하나의 결과만 있어도 충분합니다.

snowall의 이미지

0~(2^n)-1 사이에 임의로 주어진 수 n개 중, 적당히 몇개를 골라서 더하여 2^n-1 mod 2^n를 만드는 알고리즘이 되겠군요.

배낭 문제의 응용형태가 되겠네요.
http://www.jlab.net/Jboard11/JBoard.jsp?action=read&index=18&page=3&tale=0&tablename=soft&way=0&maxrow=18&searchtype=&keyword=&category=

피할 수 있을때 즐겨라! http://melotopia.net/b

pogusm의 이미지

천천히 읽어보고 있는데... 어렵네요 ㅠㅠ
좀더 집중해서 읽어봐야겠네요..
근데 문제가 다 보이지 않네요..

어떤 도둑이 금고 안에 크기와 그 값이 다른 N개 유형의 물건들이 있음을 알았다. 그러나 그 도둑은 용량이 M인 작은 배낭 하나만을 갖고 있다. 배낭문제는 가지고 가는 물건들의 총 값어치가 최대가 되도록 물건들의 조합을 선택하는 것이다.
예로서, 배낭의 용량이 17이고, 금고 안에는 아래 그림과 같이 각기 크기와 값이 다른 물건들이 있다고 하자. 이

까지만 보이네요

암튼 답변 감사합니다.

배낭문제 에 대해서 검색해봐야겠습니다

snowall의 이미지

10진수로 간주하고, 작은수부터 큰 수 순서대로 오름차순으로 정렬한 후, 위에서부터 하나씩 적당히 골라가면 될 것 같은데요.

이건 욕심쟁이 방법의 응용이겠죠.

피할 수 있을때 즐겨라! http://melotopia.net/b

pogusm의 이미지

욕심쟁이 방법 이란것도 배낭문제랑 비슷한건가요?
좋은 힌트 감사합니다.
검색해봐야겠네요

winner의 이미지

욕심쟁이 방법 (Greedy Method) 가 배낭문제의 적정결론을 찾기 위한 방법일뿐 최적값의 해법은 아닙니다.
동적계획법 (Dynamic Programming) 도 마찬가지죠.

winner의 이미지

동적계획법 (Dynamic Programming) 이 필요한 경우는 흔치 않은데 오랜만에 보네요.
공부 목적이 아니라면 뭐에 쓰는 걸까요?

pogusm의 이미지

개인용도의 프로그래밍을 하다 삼천포로 빠지면서 위의 문제에 맞닥드렸는데
호기심이 생겨서 최적화된 값을 계산하다보니 이렇게 kldp까지 오게되었습니다.
근데 쉽지 않네요...
동적계획법이란것도 검색해봐야겠습니다.

근데 최대 n^3 이면 된다는건 무슨 뜻인가요??

winner의 이미지

이건 snowall님 말대로 배낭문제의 응용입니다.
조금 더 정확히 하면 0-1 배낭문제인데 NP 완전문제죠.
다른 해법이 가능한지는 모르겠네요.

pogusm의 이미지

넵 조언 감사합니다

익명 사용자의 이미지

잘알려진 유형일것 같긴한데요..

그냥해보라하면,
1. N개 중 1의 개수가 제일 많은 1개를 고른다.
2. 나머지 N-1개에 대하여 미리 고른 1개가 1인 자리수의 1을 모두 0으로 바꾼다.
3. 1-2 를 나머지 N-1개에 대하여 1이 하나도 남지 않을때까지 반복한다.

라고 하면 일단 어떻게든 하나의 답을 찾을 수 있을 것 같습니다.

global optimal을 찾기는 무척어려울것 같네요..

pogusm의 이미지

좋은 힌트 감사합니다.
쉽지는 않을거 같네요 ㅠㅠ

익명 사용자의 이미지

이렇게?
당연히 global optimal 절대 아닙니다.

user@localhost:~/kldp/ $ cat in.txt
1111101100110001100001100000
1111011010101001010001010000
1110110110011000110000110000
1101111001100101001001001000
1011110101010100101000101000
0111110011001100011000011000
1101001111100011000101000100
1010101111010010100100100100
0110011111001010010100010100
0001111111000110001100001100
1101001000111111000011000010
1010100100111110100010100010
0110010010111110010010010010
0001110001111110001010001010
0000001111111110000110000110
1101001000100001111111000001
1010100100010001111110100001
0110010010001001111110010001
0001110001000101111110001001
0000001111000011111110000101
0000000000111111111110000011
1101001000100001000001111111
1010100100010000100001111111
0110010010001000010001111111
0001110001000100001001111111
0000001111000010000101111111
0000000000111110000011111111
0000000000000001111111111111
 
user@localhost:~/kldp/ $ cat ./main.py
#!/usr/bin/python3
import array
import sys
def bitLenCount(int_type):
    count = 0
    while (int_type):
        count += (int_type & 1)
        int_type >>= 1
    return count
 
data = array.array('L')
for line in open( sys.argv[1] ):
    v = int( line.strip(), 2 )
    if v in data:
        print('duplicated data. exit')
        sys.exit(1)
    data.append( v )
 
result=[]
while 1:
    k = 0
    for i in data:
        k = k | i
    if k == 0:
        break
 
    max_bitlen = 0
    for i in data:
        bitlen = bitLenCount(i)
        if bitlen > max_bitlen:
            max_bitlen = bitlen
            max_data = i
 
    result.append( data.index( max_data ) + 1 )
 
    for i, v in enumerate( data ):
        data[i] = v & ~max_data
 
print(result)
 
user@localhost:~/kldp/ $ ./main.py in.txt
[1, 6, 15, 16]
pogusm의 이미지

엄청 감사합니다.
파이썬은 잘 모르지만, c를 조금 할줄 알아서 어느정도 이해는 할 수 있을거 같습니다.
좋은 참고가 될거 같습니다.
감사합니다
굽신굽신

익명 사용자의 이미지

도움이 되셨다니 뿌듯하네요..ㅎㅎ

코드에서 해가없는 경우 무한루프에 빠지는 조건이 빠졌네요.
적당한 위치에, len(result) == len(data) 이면 해없음을 추가해야겠네요..

익명 사용자의 이미지

아! 필요없군요..ㅠ.ㅠ

pogusm의 이미지

소스코드 잘 보았습니다~
C++에서도 적용할 수 있을거 같습니다.

2진수를 int로 가져오는 부분을 c++에서 적용하려면
길이가 28인 이진수는 처리가 가능할테지만..
길이가 84, 210, 5005 으로 길어지면... int로 가져와서 처리할수는 없고,
문자열로 하나하나 비교를 하면서 처리를 해야할거 같습니다..

근데, 파이썬에서는 무한대의 자료형이 존재한다고 본거같은데...

111111100011100000001110000000000001110000000000000000001110000000000000000000000000
111110011010011000001001100000000001001100000000000000001001100000000000000000000000
111101010101010100000101010000000000101010000000000000000101010000000000000000000000
111100101100101100000010110000000000010110000000000000000010110000000000000000000000
110011111010000011001000001100000001000001100000000000001000001100000000000000000000
101011110101000010100100001010000000100001010000000000000100001010000000000000000000
100111101100100001100010000110000000010000110000000000000010000110000000000000000000
011011011100010010010001001001000000001001001000000000000001001001000000000000000000
010110111100001001010000100101000000000100101000000000000000100101000000000000000000

84bit길이의 이진수를 적용해 보려고 하니까... 안되는데..

v = int( line.strip(), 2 ) 부분을
v = long( line.strip(), 2 ) 으로 바꿔봐도 안되던데...

84bit길이의 이진수를 처리하려면 어느 부분을 수정하면 될까요?

winner의 이미지

길이를 동적으로 받을 생각이 아니라면 std::bitset으로 충분하고, 동적으로 해야 한다면 boost dynamic_bitset 을...

pogusm의 이미지

C++ 에서 std::bitset 이라는것이 있었나보군요!

오늘 정말 많은거 배워갑니다 ㅋㅋ

감사합니다~

익명 사용자의 이미지

data = array.array('L') 를 그냥 data = [] 로하시면 되겠습니다.. ^^;;
python은 잘 몰라서.. ^^;;

좀 간략한 버전입니다.
아까는 python3 이고 지금은 python2.6 입니다.

#!/usr/bin/python
import sys
 
int2bstr = lambda n: n>0 and int2bstr(n>>1)+str(n&1) or ''
 
data = []
for line in open( sys.argv[1] ):
    v = int( line.strip(), 2 )
    if v in data:
        print('duplicated data. exit')
        sys.exit(1)
    data.append( v )
 
result=[]
while 1:
    if  reduce( lambda x,y:x|y, data) == 0 :
        break
 
    bitlens = map( lambda n:int2bstr(n).count('1') , data)
    max_idx = bitlens.index( max( bitlens ) )
    max_data = data[max_idx]
    result.append( max_idx + 1 )
 
    data = map( lambda x: x & ~max_data, data )
 
print result

pogusm의 이미지

data=[]라고 바꾸니까 바로 잘 되네요 ^^

lambda를 잘 모르겠어서 그냥 긴 코드로 사용하였습니다

감사합니다~

나그네나그네의 이미지

쩝... 재밌는 글이었는데 벌써 완료가 달렸네요 -_-;;; 그래도 혹시나 도움 될까봐 적습니다 ㅎㅎ

먼저, 이 문제는 np 문제입니다. 이유는 n-sat 문제가 np인 것과 동치입니다.

증명을 하자면 다음과 같습니다. 만약 'i번째 데이터를 선택했는가?' 변수를 x_i라고 합시다. 만약 x_i가 true이면 i번째 데이터는 선택된 것이며 x_i가 false이면 i번째 데이터는 선택하지 않았다고 합시다.(줄은 총 28개가 있으니 i는 1 이상 28 이하겠죠 ㅎ)
데이터는 본글과 같이 주어졌다고 하겠습니다.
이 때, 우리는 j번째 bit이 1이 되기 위한 조건을 x_i에 대한 boolean expression으로 나타낼 수 있습니다.
예를 들어, 본문의 28개의 데이터에서, 1번째 bit를 1로 만들기 위한 x_i의 조합은 다음 식을 만족하는 조합입니다 :

조건 E1 = x_1 OR x_2 OR x_3 OR x_4 OR x_5 OR x_7 OR x_8 OR x_11 OR x_12 OR x_16 OR x_17 OR x_22 OR x_23
만약 E1이 true가 된다면, 1번쨰 bit이 1이 될 수 있습니다.

이와 같이 E2, E3, E4, ..., En을 식을 세울 수 있습니다.

우리가 원하는 것은 모든 bit가 1이 되는 것이니,
E1 & E2 & E3 & ... & E(n-1) & En
가 true가 되도록 x_i를 잘 고르는 것이 목적입니다. 그 다음, x_i가 true인 i에 대해서 i번째 data를 뽑으면 답이 나옵니다.

그러나 위의 경우 변수의 갯수가 3개 이상이므로 n-SAT 문제와 같습니다. 따라서 optimal solution을 구하는 것은 np 문제입니다.

approximated solution으로 greedy algorithm을 제시하셧는뎅.. greedy algorithm을 처음부터 쓰는 방법은 근사해를 구할 수 없다고 생각합니다-_-; 이유는 상한값이 없기 때문입니다..

개인적으로 추천하는 방법은 Minimum vertex cover를 사용하는 방법입니다. minimum vertex cover란, "graph에서 어떤 노드 subset N'을 선택했을 때, N'과 인접한 노드들과 N'을 합집합하면 graph의 전체 노드set과 같다. 이 때, sizeof(N')이 최소가 되는 set N'"입니다.
Minimum vertex cover는 일반적인 graph에 대해서는 np이지만, bipartite graph에 대해서는 koenig's algorithm을 이용해 O(n^3)만에 계산이 가능합니다.

음... 대략적으로 방법을 서술만 해보자면 -_-;

bipartite graph를 다음과 같이 정의해 보겠습니다.
node p_i : i번째 data를 나타내는 node
node q_j : j번째 bit를 나타내는 node
그리고 p_i의 전체 집합을 P, 노드 q_j의 전체 집합을 Q라 하겠습니다.
그리고 node p_i와 node q_j에 대해서, i번째 data의 j번째 bit가 1일 때 node p_i와 node q_j가 연결되어 있다고 정의를 합니다.

이 때, 주어진 bipartite graph에 대해 maximum bipartite matching을 계산한 뒤 koenig's algorithm을 구하면 P와 Q를 모두 포함한 node에 대한 minimum vertex cover S = P' 합집합 Q'가 나옵니다.
허나 구하고자 하는 것은 P의 subset이므로..(우리가 선택하는 것은 data이기 때문입니다) 방금 구한 P'와 Q'에서 Q'를 P쪽으로 projection 시켜야 정확한 근사해가 나옵니다. 이 과정은 '그냥' 해도 되고, 더 효율 향상을 위해서는 greedy하게 선택을 해도 됩니다.

시간복잡도는 maximum bipartite matching + koenig's algorithm이니 O(N^3)이며, 근사해의 상한값은 문제를 bipartite graph로 표현했을 떄의 minimum vertex cover 갯수입니다. 얼추 optimal solution의 2배에서 logN 배 정도 범위 안에서 놀 듯 합니다.

혹여나! pogusm님께 근사해를 구하는 것이 매우 중요한 문제가 아닐까 해서 다소 알고리즘을 생각해본 끝에 적어보았습니다 ㅎ

pogusm의 이미지

와.. 뭔가 굉장히 복잡한 이야기인것 같습니다.
제가 관련분야를 제대로 공부해보지 못해서 정말 생소합니다.
하지만 분명 저에게 중요한 자료가 될거 같습니다.

위의 다른분들의 도움 덕에 해답에 가까워 질 수 있었지만..
결과값이 분명 유효한 값이긴 하지만 "최소조합"은 아니었다는 것을 확인 할 수 있었습니다

$ cat in2.txt
111111100011100000001110000000000001110000000000000000001110000000000000000000000000
111110011010011000001001100000000001001100000000000000001001100000000000000000000000
111101010101010100000101010000000000101010000000000000000101010000000000000000000000
111100101100101100000010110000000000010110000000000000000010110000000000000000000000
110011111010000011001000001100000001000001100000000000001000001100000000000000000000
101011110101000010100100001010000000100001010000000000000100001010000000000000000000
100111101100100001100010000110000000010000110000000000000010000110000000000000000000
011011011100010010010001001001000000001001001000000000000001001001000000000000000000
010110111100001001010000100101000000000100101000000000000000100101000000000000000000
001101111100000100110000010011000000000010011000000000000000010011000000000000000000
110010000011111011001000000000110001000000000110000000001000000000110000000000000000
101001000011110110100100000000101000100000000101000000000100000000101000000000000000
100100100011101101100010000000011000010000000011000000000010000000011000000000000000
011000010011011110010001000000100100001000000100100000000001000000100100000000000000
010100001010111101010000100000010100000100000010100000000000100000010100000000000000
001100000101111100110000010000001100000010000001100000000000010000001100000000000000
000011010011010011110000001000100010000001000100010000000000001000100010000000000000
000010101010101011110000000100010010000000100010010000000000000100010010000000000000
000001100101100111110000000010001010000000010001010000000000000010001010000000000000
000000011100011111110000000001000110000000001000110000000000000001000110000000000000
110010000010000000001111101100110001000000000000001100001000000000000001100000000000
101001000001000000001111011010101000100000000000001010000100000000000001010000000000
100100100000100000001110110110011000010000000000000110000010000000000000110000000000
011000010000010000001101111001100100001000000000001001000001000000000001001000000000
010100001000001000001011110101010100000100000000000101000000100000000000101000000000
001100000100000100000111110011001100000010000000000011000000010000000000011000000000
000011010000000010001101001111100010000001000000001000100000001000000001000100000000
000010101000000001001010101111010010000000100000000100100000000100000000100100000000
000001100100000000100110011111001010000000010000000010100000000010000000010100000000
000000011100000000010001111111000110000000001000000001100000000001000000001100000000
000000000011010010001101001000111110000000000100001000010000000000100001000010000000
000000000010101001001010100100111110000000000010000100010000000000010000100010000000
000000000001100100100110010010111110000000000001000010010000000000001000010010000000
000000000000011100010001110001111110000000000000100001010000000000000100001010000000
000000000000000011110000001111111110000000000000010000110000000000000010000110000000
110010000010000000001000000000000001111101100110001100001000000000000000000001100000
101001000001000000000100000000000001111011010101001010000100000000000000000001010000
100100100000100000000010000000000001110110110011000110000010000000000000000000110000
011000010000010000000001000000000001101111001100101001000001000000000000000001001000
010100001000001000000000100000000001011110101010100101000000100000000000000000101000
001100000100000100000000010000000000111110011001100011000000010000000000000000011000
000011010000000010000000001000000001101001111100011000100000001000000000000001000100
000010101000000001000000000100000001010101111010010100100000000100000000000000100100
000001100100000000100000000010000000110011111001010010100000000010000000000000010100
000000011100000000010000000001000000001111111000110001100000000001000000000000001100
000000000011010010000000000000100001101001000111111000010000000000100000000001000010
000000000010101001000000000000010001010100100111110100010000000000010000000000100010
000000000001100100100000000000001000110010010111110010010000000000001000000000010010
000000000000011100010000000000000100001110001111110001010000000000000100000000001010
000000000000000011110000000000000010000001111111110000110000000000000010000000000110
000000000000000000001101001000100001101001000100001111110000000000000001000001000001
000000000000000000001010100100010001010100100010001111110000000000000000100000100001
000000000000000000000110010010001000110010010001001111110000000000000000010000010001
000000000000000000000001110001000100001110001000101111110000000000000000001000001001
000000000000000000000000001111000010000001111000011111110000000000000000000100000101
000000000000000000000000000000111110000000000111111111110000000000000000000010000011
110010000010000000001000000000000001000000000000000000001111101100110001100001100000
101001000001000000000100000000000000100000000000000000001111011010101001010001010000
100100100000100000000010000000000000010000000000000000001110110110011000110000110000
011000010000010000000001000000000000001000000000000000001101111001100101001001001000
010100001000001000000000100000000000000100000000000000001011110101010100101000101000
001100000100000100000000010000000000000010000000000000000111110011001100011000011000
000011010000000010000000001000000000000001000000000000001101001111100011000101000100
000010101000000001000000000100000000000000100000000000001010101111010010100100100100
000001100100000000100000000010000000000000010000000000000110011111001010010100010100
000000011100000000010000000001000000000000001000000000000001111111000110001100001100
000000000011010010000000000000100000000000000100000000001101001000111111000011000010
000000000010101001000000000000010000000000000010000000001010100100111110100010100010
000000000001100100100000000000001000000000000001000000000110010010111110010010010010
000000000000011100010000000000000100000000000000100000000001110001111110001010001010
000000000000000011110000000000000010000000000000010000000000001111111110000110000110
000000000000000000001101001000100000000000000000001000001101001000100001111111000001
000000000000000000001010100100010000000000000000000100001010100100010001111110100001
000000000000000000000110010010001000000000000000000010000110010010001001111110010001
000000000000000000000001110001000100000000000000000001000001110001000101111110001001
000000000000000000000000001111000010000000000000000000100000001111000011111110000101
000000000000000000000000000000111110000000000000000000010000000000111111111110000011
000000000000000000000000000000000001101001000100001000001101001000100001000001111111
000000000000000000000000000000000001010100100010000100001010100100010000100001111111
000000000000000000000000000000000000110010010001000010000110010010001000010001111111
000000000000000000000000000000000000001110001000100001000001110001000100001001111111
000000000000000000000000000000000000000001111000010000100000001111000010000101111111
000000000000000000000000000000000000000000000111110000010000000000111110000011111111
000000000000000000000000000000000000000000000000001111110000000000000001111111111111

$ cat main.py
#!/usr/bin/python
import array
import sys
def bitLenCount(int_type):
    count = 0
    while (int_type):
        count += (int_type & 1)
        int_type >>= 1
    return count
 
data = []
for line in open( sys.argv[1] ):
    v = int( line.strip(), 2 )
    if v in data:
        print('duplicated data. exit')
        sys.exit(1)
    data.append( v )
 
 
result=[]
while 1:
    k = 0
    for i in data:
        k = k | i
    if k == 0:
        break
 
    max_bitlen = 0
    for i in data:
        bitlen = bitLenCount(i)
        if bitlen > max_bitlen:
            max_bitlen = bitlen
            max_data = i
 
    result.append( data.index( max_data ) + 1 )
 
    for i, v in enumerate( data ):
        data[i] = v & ~max_data
 
print(result)
 
 
$ ./main.py in2.txt
[1, 20, 84, 24, 43, 69, 4, 6, 11]

01.111111100011100000001110000000000001110000000000000000001110000000000000000000000000
04.111100101100101100000010110000000000010110000000000000000010110000000000000000000000
06.101011110101000010100100001010000000100001010000000000000100001010000000000000000000
11.110010000011111011001000000000110001000000000110000000001000000000110000000000000000
20.000000011100011111110000000001000110000000001000110000000000000001000110000000000000
24.011000010000010000001101111001100100001000000000001001000001000000000001001000000000
43.000010101000000001000000000100000001010101111010010100100000000100000000000000100100
69.000000000001100100100000000000001000000000000001000000000110010010111110010010010010
84.000000000000000000000000000000000000000000000000001111110000000000000001111111111111

84*84 크기의 데이터를 위의 프로그램으로 실행해본 결과 "9조합" 의 결과를 얻을 수 있었는데...

84줄에 대해서 84C8 에 해당하는 경우의수로 훑어보니(무식한방법이지만 혹시나 해서 돌려보았습니다)
"8조합"으로도 가능하다는 사실을 알 수 있었습니다.
8조합으로 이루어진 그해는 수백개 이상이며(중간에 루프를 중단해서..)

그중 예를 들자면 아래와 같습니다.

01.111111100011100000001110000000000001110000000000000000001110000000000000000000000000
02.111110011010011000001001100000000001001100000000000000001001100000000000000000000000
03.111101010101010100000101010000000000101010000000000000000101010000000000000000000000
04.111100101100101100000010110000000000010110000000000000000010110000000000000000000000
35.000000000000000011110000001111111110000000000000010000110000000000000010000110000000
50.000000000000000011110000000000000010000001111111110000110000000000000010000000000110
71.000000000000000011110000000000000010000000000000010000000000001111111110000110000110
84.000000000000000000000000000000000000000000000000001111110000000000000001111111111111
[1 2 3 4 35 50 71 84]
 
이 외에도
[1 2 3 4 35 55 76 83]
[1 2 3 4 35 56 77 82]
[1 2 3 4 35 82 83 84]
[1 2 3 4 50 55 77 82]
.. 수백수천개 ..

84줄에 대해서 84c7에 해당하는 경우의 수로 루프를 돌려보니 "7조합"으로도 가능하기도 했습니다.

01.111111100011100000001110000000000001110000000000000000001110000000000000000000000000
02.111110011010011000001001100000000001001100000000000000001001100000000000000000000000
03.111101010101010100000101010000000000101010000000000000000101010000000000000000000000
35.000000000000000011110000001111111110000000000000010000110000000000000010000110000000
50.000000000000000011110000000000000010000001111111110000110000000000000010000000000110
74.000000000000000011110000000000000010000000000000010000000000001111111110000110000110
84.000000000000000000000000000000000000000000000000001111110000000000000001111111111111
[1 2 3 35 50 71 84]
 
이 외에도
[1 2 3 35 55 76 83]
[1 2 3 35 56 77 82]
[1 2 3 35 82 83 84]
[1 2 3 50 55 77 82]
.. 수백수천개 ...

각 줄마다 [1 = 19개] + [0 = 65개] = 84개 으로 구성되어 있으므로
이를 단순 계산해보면 84/19 = 4.42
즉, 최소 5조합으로도 어쩌면 가능할지도 모르겠습니다.
(하지만 6조합, 5조합의 해를 찾는 루프는 돌려보지 못했습니다 - 추가 : 6조합의 해를 찾기 위한 루프를 돌려보았으나 그 해가 없었습니다. 즉 7조합이 최소조합이었습니다.)

결론:
9조합의 결과를 얻는 알고리즘도 괜찮긴 하지만
보다 나은 방법이 있을 수도 있겠다라는 결론을 얻었습니다.

좋은글 참고로 하여 좀더 공부해봐야겠습니다.

감사합니다.

winner의 이미지

http://kldp.org/node/106607

이 문제는 순열이 아니라 조합이라는 차이가 있기는 합니다.

pogusm의 이미지

n queen 이 뭔지도 모르는지라,
체스의 퀸의 역할부터 시작해서..
하스켈, minisat 까지 검색해서, 실습까지는 해보았습니다.

일단 8x8 체스판에서 겹치지 않게 퀸의 위치를 계산해 낼수 있는 프로그램이 있다는것 자체가 놀랍습니다.

알려주신 링크를 보면
$ runhaskell NQueenCNF.hs > q8.cnf 실행에 따라 생성된 q8.cnf의 내용은 아래와 같습니다.

p cnf 64 744
1 2 3 4 5 6 7 8 0
9 10 11 12 13 14 15 16 0
17 18 19 20 21 22 23 24 0
25 26 27 28 29 30 31 32 0
33 34 35 36 37 38 39 40 0
41 42 43 44 45 46 47 48 0
49 50 51 52 53 54 55 56 0
57 58 59 60 61 62 63 64 0
-1 -2 0
-1 -3 0
-1 -4 0
-1 -5 0
-1 -6 0
-1 -7 0
-1 -8 0
-2 -3 0
-2 -4 0
-2 -5 0
-2 -6 0
-2 -7 0
-2 -8 0
-3 -4 0
-3 -5 0
-3 -6 0
-3 -7 0
-3 -8 0
-4 -5 0
-4 -6 0
-4 -7 0
-4 -8 0
-5 -6 0
-5 -7 0
-5 -8 0
..생략...

대충 문법이 이해는 갑니다만....

제가 하려는 것을 cnf으로 작성할수 있는건지는 모르겠습니다 ㅠㅠ
저의 문제를 cnf로 작성해서 minisat으로 해결이 가능한건가요?

winner의 이미지

-_-.

imyejin님의 글만으로는 최적값을 찾는데 적합한지는 알 수 없습니다.
적정한 CNF 생성 program을 만드는게 더 어려울 수도 있죠.

공부하는 열정은 부러울 정도네요.
N Queen 을 모르신다는 것을 보면 컴퓨터 과학 혹은 컴퓨터 공학을 전공하신 것 같지는 않네요.
기회가 되신다면 관련 교과서적을 차근차근 공부해보는 것도 좋을 것 같습니다.

추천 서적으로는 제가 읽어본 것 중에 이정도...
http://www.aladin.co.kr/shop/wproduct.aspx?ISBN=8960550809
http://www.aladin.co.kr/shop/wproduct.aspx?ISBN=8945070117

이 문제랑은 상관없습니다.

pogusm의 이미지

맨땅에 헤딩하는건 역시 한계가 있는거 같습니다. ㅋㅋ
제대로 알려면 정말 책이라도 봐야할거 같습니다.

아무튼 이래저래 많은걸 배웠습니다.

도움주셔서 감사합니다~

pogusm의 이미지

.

pogusm의 이미지

.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.