KMP 알고리즘

A/Algorithm 2011. 10. 28. 12:41
#include 
#include 
char s[1000]={0},p[100]={0};
int n,m,pi[100]={0};
void find_pi()
{
int i=0,j=-1;
pi[0]=-1;
while(i < m)
{
if(j==-1 || p[i]==p[j])
{
i++,j++;
pi[i]=j;
}
else j=pi[j];
}
}
void kmp()
{
int i=0,j=0;
while(i < n)
{
if(j==-1 || s[i]==p[j]) i++,j++;
else j=pi[j];
if(j==m)
{
printf("Match : %d to %d\n",i-m+1,i);
j=pi[j];
}
}
}
int main(void)
{
scanf("%s",s);
scanf("%s",p);
n=strlen(s),m=strlen(p);
find_pi();
kmp();
return 0;
}
출처 : http://211.228.163.31/30stair/KMP_doc/KMP_doc.php?pname=KMP_doc

'A > Algorithm' 카테고리의 다른 글

연결성 문제를 위한 가중 퀵병합 방식  (0) 2011.10.27
재밋는? 러시아 페인트공 알고리즘  (0) 2011.10.27
냅색(Knapsack:배낭) 문제  (0) 2011.10.27
토끼와 거북이 알고리즘  (0) 2011.10.27
XOR 교체 알고리즘  (0) 2011.10.27

설정

트랙백

댓글


// 가중 퀵병합

#include <stdio.h>

#define N 50

int main(void)

{

int i, j, p, q, id[N], sz[N];

for(i=0; i<N; i++) // 초기화

id[i] = i, sz[i] = 1;

while(scanf("%d %d", &p, &q) == 2){

for(i = p; i != id[i]; i = id[i]); // p의 부모 노드 찾기

for(j = q; j != id[j]; j = id[j]); // q의 부모 노드 찾기

if(i == j) // 부모노드가 같을 경우 패스

continue;

if(sz[i] > sz[j]){

id[j] = i, sz[i] += sz[j];

} else if(sz[i] <= sz[j]){

id[i] = j, sz[j] += sz[i];

}

}

for(i=0; i<N; i++) // 출력 예

printf("%d ", id[i]);

puts("");

return 0;

}

+++++++ 절반 분할에 의한 경로 압축 +++++++ // 이것을 하는 것과 안하는 차이는 미묘하다고 전해짐

for(i = p; i != id[i]; i = id[i])

id[i] = id[id[i]];

for(j = q; j != id[j]; j = id[j])

id[j] = id[id[j]];

'A > Algorithm' 카테고리의 다른 글

KMP 알고리즘  (0) 2011.10.28
재밋는? 러시아 페인트공 알고리즘  (0) 2011.10.27
냅색(Knapsack:배낭) 문제  (0) 2011.10.27
토끼와 거북이 알고리즘  (0) 2011.10.27
XOR 교체 알고리즘  (0) 2011.10.27

설정

트랙백

댓글


도로 차선 페인트 작업을 하는 러시아 페인트공이 있었습니다. 작업 첫날 페인트공은 페인트 통을 들고 나가서 300야드를 칠했습니다. 깜짝 놀란 책임자는 "정말 놀라운데! 정말 손놀림이 좋군."이라며, 페인트공에게 1코펙을 주었습니다.
다음날 페인트공은 겨우 150야드만 칠했습니다. 그래도 책임자는 "음, 어제 만큼은 못하지만, 여전히 손놀림이 좋아. 150야드도 대단하지."라며, 1코펙을 주었습니다.
그 다음날 페인트공은 30야드를 칠했습니다. 책임자는 "고작 30야드라니! 용납할 수 없네! 첫날에는 어떻게 오늘보다 10배를 넘게 칠한건가? 도대체 뭐가 문제야?"라고 윽박질렀습니다.
풀이 죽은 페인트공은 이렇게 말했습니다. "저도 어쩔 수 없었습니다. 매일 페인트통에서 점점 멀어지니까요."

- 조엘 온 소프트웨어 中, 조엘 스폴스키

이것이 러시아 페인트공 알고리즘이다. 자... 이제 다음의 C언어 코드를 보자... 두 문자열을 합하는 코드이다. 무엇이 문제일까??

void strcat(char * dest, char * src)
{
while (*dest) dest++;
while (*dest++ = *src++);
}

아주 간단하면서도 명확해 보이는 코드이다. 물론 동작도 잘 한다. 하지만 과연 성능도 괜찮을까?? 위의 함수로 아래의 코드를 실행한다고 생각해 보자. 여러 사람의 이름을 문자열 하나에 이어 붙이는 문제이다.

char bigString [1000]; /- 얼마나 할당해야 할지 알 수 없음... *-
bigString[0] = '\0';
strcat(bigString, "John, ");
strcat(bigString, "Paul, ");
strcat(bigString, "George, ");
strcat(bigString, "Joel ");

이 함수(strcat)는 러시아 페인트공 알고리즘을 사용하고 있다. 한 문자열을 이어 붙이기 위해서는 이전의 문자열의 끝을 찾아 문자열 처음 부터 끝까지 이동을 해야 한다. C언어는 ASCIZ 문자열 타입을 사용하기 때문이다. ASCIZ는 문자열 끝이 영(Zero)로 끝나는 ASCII라는 뜻이다. 파스칼 같은 경우는 ASCII 문자열을 사용하지만 문자열의 길이를 저장하기 때문에 문자열 끝이 영으로 끝날 필요가 없어 ASCIZ를 사용한다고 볼 수는 없다.

자... 그럼 저 strcat 함수를 바꿔보자.

char * mystrcat(char * dest, char * src)
{
while (*dest) dest++;
while (*dest++ = *src++);
return --dest;
}

char bigString [1000]; /- 얼마나 할당해야 할지 알 수 없음... *-
char * p = bigString;
bigString[0] = '\0';
p = mystrcat(p, "John, ");
p = mystrcat(p, "Paul, ");
p = mystrcat(p, "George, ");
p = mystrcat(p, "Joel ");

차이가 보이는가?? 간단한 트릭이다. 러시아 페인트공 처럼 매일 페인트 통을 찾아 처음부터 가지 말고, 문자열의 끝을 표시해둔다(return --dest;). 그리고 그 끝을 이용하면 된다. 똑같은 일을 매번 반복하는 것은 그 일이 늘어나는 경우 상당한 오버헤드로 작용할 수 있다. 이렇게 러시아 페인트공 알고리즘은 선형 효율을 보여야 할 곳에서 O(n2)[잘 안 보이네... O(n제곱), O(n*n)]의 시간 복잡도를 보이는 알고리즘이다.
--------------------------------------------------------------------------------------
파스칼은 문자열의 첫 바이트에 바이트 개수를 저장하는 방법으로 해결 - 파스칼 문자열
파스칼 문자열은 널 문자로 끝나지 않는다. 바이트에 들어가는 가장 큰 숫자가 255이므로
파스칼은 문자열을 255바이트로 길이 제한. 문자열 길이를 재기 위해 루프를 돌 필요가 없음
옛 매킨토시 운영체제와 많은 C 프로그래머가 속력 문제로 파스칼 문자열 사용.
엑셀은 내부적으로 파스칼 문자열을 사용해서 번개같이 빠름. 곳곳에 255바이트로 길이 제한.
--------------------------------------------------------------------------------------
C 코드에 파스칼 문자열 넣는 방법.
char* str = "\-06Hello!"; 바이트를 손으로 헤아려야함..
게으른 프로그래머
char* str = "*Hello!";
str[0] = strlen(str)-1; 빌어먹을 문자열 (널 문자로 끝난 파스칼 문자열)

출처 : http://blog.naver.com/midas82/50012460432

'A > Algorithm' 카테고리의 다른 글

KMP 알고리즘  (0) 2011.10.28
연결성 문제를 위한 가중 퀵병합 방식  (0) 2011.10.27
냅색(Knapsack:배낭) 문제  (0) 2011.10.27
토끼와 거북이 알고리즘  (0) 2011.10.27
XOR 교체 알고리즘  (0) 2011.10.27

설정

트랙백

댓글


출처 : http://devils9curse.tistory.com/11


냅색 문제라는 것이 있습니다.

주어진 가방이 있을 때 가치가 최대한이 되도록 물건을 담는 것이죠.

그런데 각 물건은 무게가 있어서, 원하는 만큼 전부 가방에 담을 수는 없습니다.

이런 냅색 문제에는 여러가지 종류가 있는데요, 거의 대부분 다이나믹으로 해결할 수 있습니다.


우선 한 물건당 물건의 수량이 1개밖에 없고 물건을 쪼갤 수도 없는 0/1 냅색이 있습니다.

이 경우의 다이나믹 테이블 정의와 점화식은 다음과 같습니다.
(W[i]:i번째 물건의 무게, P[i]:i번째 물건의 가치

D[i][j]:i물건까지를 j크기의 가방에 담았을 때 최대 가치
D[i][j]=MAX(D[i-1][j],D[i-1][j-W[i]]+P[i]) :(j>=W[i])
=D[i-1][j] :(j<W[i])

그리고 물건을 쪼갤 수는 없지만 물건의 수량이 여러개인 경우로 변형을 할 수 있는데요,

일단 물건의 개수가 유한개로 주어진 경우에는 두가지 풀이가 있습니다.

하나는 각 물건당 여러개를 담았을 때의 무게와 가치를 전부 데이터에 넣어서 0/1 냅색을 하는 것이죠.

또 다른 방법은, 다이나믹을 약간 다르게 돌리는 것입니다.

D[i][j]:i물건까지를 j크기의 가방에 담았을 때 최대 가치
D[i][j]=MAX(D[i-1][j],D[i-1][j-W[i]*k]+P[i]*k) :(j>=W[i]*k)
=D[i-1][j] :(j<W[i]*k)

별 차이는 없죠?


물건의 개수가 무한개로 주어지는 경우를 보겠습니다.

이번에는 1차원 다이나믹만으로도 해결이 가능합니다.

D[j]:j크기의 가방에 담았을 때 최대 가치
D[j]=MAX(D[j],D[j-W[i]]+P[i]) (j>=W[i])

마지막 경우로는, 물건을 쪼갤 수 있는 경우가 되겠는데요, 이런 경우에는 그리디로도 해결이 가능합니다.

무게 1당 가치가 높은 순으로 넣을 수 있는 만큼 차례대로 넣으면 되죠.

냅색 문제는 여러 방법으로도 활용이 가능하니, 잘 알아 두시는 것이 좋습니다.

설정

트랙백

댓글


출처 : http://minjang.egloos.com/1687021

영어 질문 하나. 우리가 잘 아는 이솝 우화, '토끼와 거북이'를 영어로 하면은? 학교에서 거북이는 Turtle로 배웠고 토끼는 Rabbit으로 배웠으니...

Rabbit and Turtle ?

안타깝게도 이것은 정답이 아니다. 토끼와 거북이는 영어로

Tortoise and Hare

로 쓴다. 내가 Rabbit and Turtle라는 말을 쓰자 인도친구가 웃으면서 Tortoise and Hare로 고쳐주더라.

그런데 정작 하고 싶은 이야기는...

Tortoise and Hare, 즉 토끼와 거북이 알고리즘이라는 것이 있다. 주어진 리스트에 싸이클이 있는지 없는지를, 보다 일반적으로 표현하면 주어진 함수에서 싸이클이 있는지 없는지를 알려주는 알고리즘이다. 이 알고리즘을 고안한 사람은 Floyd라는 사람이다. 알고리즘 책에서 본, 그 짧은 코드에도 불구 오묘한 기능을 하는 All Shortest Path 알고리즘을 만든 그 Floyd이다.

그림을 그려서 다시 이 문제를 설명하면,

image

링크드 리스트에서 O(n) 시간과 O(1) 저장 공간을 이용해서 싸이클이 있는지 없는지를 알아내어라.

만약 시간과 저장 공간의 제약이 없다면, 노드마다 방문 되었는지 기억하는 변수를 하나 두고 돌아다니면 될 것이다. 그러나 문제에서는 O(1)의 공간, 즉 이런 추가적인 변수를 둘 수 없다. 그렇다면 일반적인 방법으로는 풀기가 어렵다. 여기서 아주 기발하게 토끼와 거북이가 등장해서 싸이클 유무를 판단할 수 있다.

  1. 거북이는 리스트를 한 번에 한 노드씩 앞으로 나아간다.
  2. 반면에 토끼는 두 걸음씩 움직인다.
  3. 이런 과정을 계속 반복한다.

만약 리스트에 싸이클이 있다면? 그렇다면 이 둘은 언젠가 만나게 될 것이다.

그림을 그려서 확인해보자. (PowerPoint 2007 만세~)

image

이렇게 보다시피 언젠가는 만나게 됨을 직관적으로 알 수 있다. Wiki에는 리스트가 아닌 함수에서 싸이클 찾는 알고리즘을 Python으로 기술하고 있다. (리스트일 경우에는 단순히 함수 f를 다음 노드를 반환해주는 것으로 만들면 될 것이다.)

def floyd(f, x0):
# The main phase of the algorithm, finding a repetition x_nu = x_2nu
# The hare moves twice as quickly as the tortoise
tortoise, hare = f(x0), f(f(x0))
while tortoise != hare:
tortoise = f(tortoise)
hare = f(f(hare))

Floyd의 논문에는 단순히 싸이클의 존재 유무를 떠나 모든 싸이클 (보다 엄밀하게는 simple cycle)을 다 찾고 나열할 수 있는 알고리즘이 나와있다 (Fig. 5~8). 그러나 정확히 위의 pseudo code처럼 토끼와 거북이를 명시한 알고리즘은 아니다.

Floyd는 이런 알고리즘을 Back-tracking 알고리즘과 구분하여 Nondeterministic 알고리즘이라고 부른다. 흔히 우리가 알고 있는 Nondeterministic Turing Machine의 행동과 비슷하다. NTM에서는 다음 스텝으로 갈 때, 일반적인 Deterministic TM처럼 한 곳으로만 가는 것이 아니라 (확률에 의존적이지가 않고) 여러 군데로 가는 것을 허용한다. Floyd가 제안한 Nondeterministic 알고리즘은 이와 유사하게 multivalued function (아래 참고)을 도입하여 비결정성을 구현하고 있다. 그러나 결국 컴퓨터로 돌리기 위해서는 deterministic 해야 하니 실제 모든 루프(=싸이클)를 찾는 알고리즘을 보면 (컴파일러 최적화에서 쓰이는 것) Floyd가 제시한 알고리즘과 매우 유사하지만 모든 스텝이 결정적으로 이루어져있다. 더 이상 쓰려니 머리가 아파서 그만...

암튼 결론은 리스트에서 싸이클을 찾고 싶을 때 토끼와 거북이를 이용하라는 것.


@ Multivalued function: 간단하게 말하면, 함수는 x원소에 대응되는 y 원소가 오직 하나 뿐임에 비해 이 multivalued function은 f(x)가 여러 개의 y 값을 가지고 있음. 즉, 일반적인 함수의 정의에는 위배됨.

@ 그냥 관심있으면 보시라고 Floyd의 논문을 직접 다운 받아 여기에 올렸는데 설마 잡아가지는 않겠지...


'A > Algorithm' 카테고리의 다른 글

재밋는? 러시아 페인트공 알고리즘  (0) 2011.10.27
냅색(Knapsack:배낭) 문제  (0) 2011.10.27
XOR 교체 알고리즘  (0) 2011.10.27
욕심쟁이(Greedy) 알고리즘  (0) 2011.10.27
리스트의 이차원 배열  (0) 2011.10.13

설정

트랙백

댓글

XOR 교체 알고리즘

A/Algorithm 2011. 10. 27. 16:27


출처 : http://ko.wikipedia.org/wiki/XOR_%EA%B5%90%EC%B2%B4_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98#.EC.8B.A4.EC.A0.9C_.EC.82.AC.EC.9A.A9.EC.97.90.EC.84.9C.EC.9D.98_.EC.9E.A5.EB.8B.A8.EC.A0.90

 

XOR 교체 알고리즘은 임시 변수를 두지 않고, 두 개의 변수를 배타적 논리합(XOR) 비트 연산을 이용하여 교체하는 알고리즘이다. 이 알고리즘은 컴퓨터 프로그래밍 분야에서 프로세서의 최적화 능력이 부족했을 때 대안으로 자주 사용되었다.

다음은 XOR 교체 알고리즘을 구현한 C 코드이다.

void swap(int *x, int *y)
{
    if (*x != *y) {
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
    }
}

이 코드는 두 포인터가 서로 다른 메모리 공간을 가리킬 때에만 교체 연산을 수행해서 문제를 제거한다.

이 코드는 종종 다음과 같은 형태로 쓰이기도 한다.

if (*x != *y) *x ^= *y ^= *x ^= *y;


실제 사용에서의 장단점

XOR 교체 알고리즘은 대부분의 현대적인 프로세서에서는 임시 변수를 사용하는 방법보다 더 느린데, 그 이유 중 하나로는 임시 변수를 사용하는 방법은 여러 명령어를 동시에 실행할 수 있도록 (명령어 수준 병렬성) 최적화하기가 더 쉽기 때문이다. XOR 교체 알고리즘은 3 연산 모두 데이터 의존성 (Read-After-Write)을 만들기에 반드시 순서대로만 실행해야한다. 따라서 현대 비순차 프로세서나 VLIW 컴파일러가 XOR 교체 알고리즘을 최적화할 수 있는 방법은 거의 없다.

반면, XOR 교체 알고리즘은 속도가 그리 빠르지 않아도 되고 메모리 (혹은 캐시) 사용을 최소화해야 하는 환경에서는 유용하게 사용될 수 있다. 따라서 이 방식은 임베디드 개발 환경에서 많이 이용된다.

'A > Algorithm' 카테고리의 다른 글

재밋는? 러시아 페인트공 알고리즘  (0) 2011.10.27
냅색(Knapsack:배낭) 문제  (0) 2011.10.27
토끼와 거북이 알고리즘  (0) 2011.10.27
욕심쟁이(Greedy) 알고리즘  (0) 2011.10.27
리스트의 이차원 배열  (0) 2011.10.13

설정

트랙백

댓글



출처 : http://blog.naver.com/dekucug/100105148371

먹고, 먹고, 또 쳐먹고. 욕심쟁이(그리디) 알고리즘

사실 이번 알고리즘의 90% 이상이 이름에 들어있습니다. 모든 알고리즘이 그런 형식이기는 하지요. Greedy란, 욕심이 많은, 탐욕스러운 이라는 뜻입니다. 그럼 대체 욕심많은 알고리즘이 무엇이냐? 컴퓨터가 어떻게 욕심을 부려서 문제를 풀 수 있다는 것일까요?

사실 이 알고리즘은 상당히 사람틱하달까, 인공지능 틱하다고 말 할수 있습니다. 간단하게, 한가지의 예를 들어 볼테니 여러분들이 한번 이 문제를 풀어보십시오.

방금 커맨드센터에서 SCV 한기가 나왔다. 당신은 그 SCV을 시켜 미네랄을 채취하게 하고 싶다. 미네랄이 총 3개 A, B, C 가있는데, 각각의 커맨드센터로 부터의 거리는 10m, 15m, 30m 이다. 이때 당신은 어느 미네랄으로 SCV를 보내는 것이 좋을까?

직관적으로 생각해 보면, 당연히 제일 가까운 10m 미네랄로 보내는 것이 옳습니다.

바로 방금, 당신은 Greedy 알고리즘을 이용한 것이지요. 단순히 욕심을 내서, 제일 가까운 미네랄로 보낸 것이니까요. 만약 욕심을 내지 않았더라면, 어디의 미네랄이든 상관 없겠지요. 만약 이번엔 거리는 다 똑같고, 각각의 자원량이 100,2000,5000 이였다면, 5000 미네랄을 선택하였겠지요. 정말 쉽습니다. 그냥 가장 좋은 방법을 택하는 것, 이것이 바로 그리디 알고리즘인 것입니다.

허나, 우리 인생을 이렇게 그리디 알고리즘으로 살면 어떻게 될까요.

분명히 망하겠지요. 그리디 알고리즘은 최적의 해가 나오기가 힘듭니다. 왜냐하면 그리디 알고리즘은 전혀 뒷일을 생각하지 않기 때문입니다. 사실 그리디 알고리즘의 정확한 의미는, '현재'상태에서 가장 좋은 방법을 택하는 것 입니다. 다시 위의 SCV 문제로 돌아가 봅시다.

분명히 위의 상황에서 가장 좋은 방법은 10m 미네랄을 선택하는 것, 그 뿐입니다. 허나 아까 말했듯이, 그리디 알고리즘은 미래를 고려하지 않습니다. 좋아라 하면서 냅다 10m 미네랄로 채취를 보냈더니, 갑자기 버로우한 저글링이 튀어나온다면 ?! 차라리 30m가는 것 만 못한 결과가 되는 것이지요.

가장 좋은것은 아니더라도 ...

사실 올림피아드 같은 최적해를 요구하는 문제풀이에서, 그리디 알고리즘은 거의 쓰이는 일이 없습니다. 그리디는 최적해가 아닌, 좋은해를 찾아주는 알고리즘이기 때문입니다. 허나 어떤 게임의 CPU 인공지능을 만드는데는 도움이 될 지도 모르지요. 왜냐하면, 인간의 사고방식을 참고한 알고리즘이니까요. 만약 이 그리디 알고리즘에, 백트래킹 알고리즘을 살짝 가미시키면 간단한 체스 인공지능 정도는 만들 수 있는겁니다. ( 우선 백트래킹(가능한 경우의 수를 체크하는것)을 이용해 자기가 갈수 있거나, 먹을수 있는 말의 갯수라던가 등의 조건을 첨가시키고 그리디를 살짝 이용하면 되겠지요. )

그렇게 생각해 보면 그리디 알고리즘은 결코 나쁜 알고리즘이라고는 할 수 없습니다. 구현하기도 쉽고, 상당히 좋은 해를 찾아주므로 오히려 좋은 알고리즘 쪽에 속한다고 볼 수도 있겠지요. 사실 올림피아드 같은 문제를 보면 제일 먼저 떠오르는것이 그리디 알고리즘입니다. 거의 대부분의 문제가 최대 또는 최소를 요구하는 문제니까요.

이런 그리디 틱한 알고리즘을 제일 먼저 생각나게 하는 문제의 유형이 몇가지 있습니다. 이미 카이스트 학습자료에도 나와 있지요. 가방 안에 가장 비싼 보석들을 담는 문제, 회의를 가장 많이 하는 문제, 행렬 내에서 연속된 연산의 최대/최소 값이라던가...

사실 그리디를 씀으로써 항상 최적해가 나오는 문제 유형이 있긴 있습니다. 대표적으로 스케쥴링 문제이지요.( 하루동안 총 몇번의 회의를 가질수 있는가 하는 문제. 예를들어 1번회의_1시~2시, 2번회의 3시~4시 라면 당연하 2개가 최대의 회의 갯수입니다 ) 이는 자료에서도 다루었고, 문제에서도 출제되었습니다. 이 문제에서 중점적으로 그리디 하게 보아야 할 것은 회의의 갯수이므로, 우선 끝나는 시간대이 빠른대로 정렬한 후, 첫번째 회의를 선택 한 뒤 그다음으로 제일 먼저 시작하는 회의를 구하면 당연히 최적해가 나옵니다. 조금만 생각해 보시면 그것이 당연하다는 것을 느끼실 수 있습니다. 스케쥴링 알고리즘의 작동 방식은 그냥 통안에 휴지들을 꾸깃꾸깃 집어넣는 방식이니까요.

이번 알고리즘은 별로 다룰게 없어서 짧게 끝났내요. 결국 그리디 알고리즘을 요약하자면,

1. 가장 좋은것을 선택하라.(물론 이때 좋은것을 선택하는 기준이 제일 중요함)

2. 항상 최적해를 보장하지는 않는다.

'A > Algorithm' 카테고리의 다른 글

재밋는? 러시아 페인트공 알고리즘  (0) 2011.10.27
냅색(Knapsack:배낭) 문제  (0) 2011.10.27
토끼와 거북이 알고리즘  (0) 2011.10.27
XOR 교체 알고리즘  (0) 2011.10.27
리스트의 이차원 배열  (0) 2011.10.13

설정

트랙백

댓글



/- 프로그램 명 : 단위 크기의 정사각형에 있는 N개의 점에 대한 순서쌍 중 몇 개가 d 보다 작은 거리를 갖는지 알아보기 *-

#include <math.h>

#include <stdio.h>

#include <stdlib.h>

#include "Point.h"

/- Point.h

typedef struct Point{

float x, y;

} Point;

*-

typedef struct node *link;

struct node{

point p;

link next;

};

link **grid; // 격자

int G;

float d; // 거리

int cnt = 0; // count

gridinsert(float x, float y)

{

int i, j;

link s;

int X = x*G + 1, Y = y*G + 1; // 삽입할 데이터의 범위(격자위치)를 찾는다.

link t = (link*) calloc(1, sizeof(*t));

t->p.x = x, t->p.y = y;

for(i = X-1; i <= X+1; i++)

for(j = Y-1; j <= Y+1; j++)

for(s = grid[i][j]; s != NULL; s = s->next)

// d 거리 이내일 경우 개수를 더한다.

if(distance(s->p, t->p) < d)

cnt++;

// 데이터를 격자 범위에다 삽입한다.

t->next = grid[X][Y], grid[X][Y] = t;

}

link **malloc2d(int r, int c) // 이차원 calloc(malloc)

{

int i;

link **t = (link**) calloc(r, sizeof(*t));

for(i=0; i<r; i++)

t[i] = (link*) calloc(c, sizeof(*t[i]));

return t;

}

int main(void)

{

int i, j, N;

scanf("%d %f", &N, &d);

G = 1/d, grid = malloc2d(G+3, G+3);

// grid 생성, G 는 격자 범위를 나타내는 수

for(i=0; i < G+3; i++)

for(j=0; j < G+3; j++)

grid[i][j] = NULL;

for(i=0; i < N; i++)

gridinsert(randFloat(), randFloat());

// 데이터 삽입 randFloat 함수는 return 1.0 * rand()/RAND_MAX; 한다

printf("%d edges shorter than %f\n", cnt, d);

return 0;

}

 

'A > Algorithm' 카테고리의 다른 글

재밋는? 러시아 페인트공 알고리즘  (0) 2011.10.27
냅색(Knapsack:배낭) 문제  (0) 2011.10.27
토끼와 거북이 알고리즘  (0) 2011.10.27
XOR 교체 알고리즘  (0) 2011.10.27
욕심쟁이(Greedy) 알고리즘  (0) 2011.10.27

설정

트랙백

댓글