'C++'에 해당되는 글 7건

  1. 2004/06/04 [C++] Orchard Trees
  2. 2004/05/18 [C++] Maximum Sum (upgrade) (2)
  3. 2004/05/10 [C++] Maximum Sum
  4. 2003/07/10 [C++] 3-dimension 63-Puzzle (1)
  5. 2003/07/10 [C++] Booth's Algorithm Simulator
http://acm.uva.es/p/v1/143.html

/**
Orchard Trees
zzun
hello82@unitel.co.kr
http://zzun.net
**/

#include <iostream.h>
#include <fstream.h>

ifstream fin;

void swap(float& a, float& b)
{
       float temp = a; a = b; b = temp;
}

bool read_input(float* x, float* y)
{
       bool rtn = false;
       for (int i=0; i<3; i++)
       {
               fin >> x[i] >> y[i];
               if ( x[i] > 0 || y[i] > 0 )
                       rtn = true;
       }

       return rtn;
}

int main()
{
       fin.open("test.in");
       float* x = new float[3];
       float* y = new float[3];
       int cur_y, count, tx1, tx2;
       float a1, a2, cur_x1, cur_x2;
       bool turn;

       while ( read_input(x, y) )
       {
               if ( y[1] < y[0] && y[1] <= y[2] )
               {
                       swap( x[0], x[1] );
                       swap( y[0], y[1] );
               }
               else if ( y[2] < y[0] && y[2] < y[1] )
               {
                       swap( x[0], x[2] );
                       swap( y[0], y[2] );
               }        // for largest y

               count = 0;
               turn = false;
               cur_y = (int) y[0];

               a1 = (x[1]-x[0])/(y[1]-y[0]);
               a2 = (x[2]-x[0])/(y[2]-y[0]);

               if ( a1 > a2 ) // which is on left side
               {
                       swap( x[1], x[2] );
                       swap( y[1], y[2] );
                       swap( a1, a2 );
               }

               cur_x1 = x[0] + a1*((float)cur_y - y[0]);
               cur_x2 = x[0] + a2*((float)cur_y - y[0]);

               while ( 1 )
               {                        
                       cur_y++;

                       if ( !turn && cur_y > y[1] && cur_y <= y[2] ) // find turning point
                       {
                               a1 = (x[2]-x[1])/(y[2]-y[1]);
                               cur_x1 = x[1] + a1*((float)cur_y - y[1]);
                               cur_x2 += a2;
                               turn = true;
                       }
                       else if ( !turn && cur_y > y[2] && cur_y <= y[1] )
                       {
                               a2 = (x[1]-x[2])/(y[1]-y[2]);
                               cur_x2 = x[2] + a2*((float)cur_y - y[2]);
                               cur_x1 += a1;
                               turn = true;
                       }
                       else
                       {
                               cur_x1 += a1;
                               cur_x2 += a2;
                       }

                       if ( (cur_y<=y[1] || cur_y<=y[2]) && cur_y<100 )
                       {
                               tx1 = ( cur_x1-(int)cur_x1 == 0 ) ? (int)cur_x1 : (int)cur_x1+1;
                               tx1 = ( tx1 == 0 ) ? 1 : tx1;
                               tx2 = ( (int)cur_x2 == 100 ) ? 99 : (int)cur_x2; // no point at 0&100
                               count += tx2 - tx1 + 1;
                       }
                       else
                               break;
               }
               
               cout << count << endl;
       }

       fin.close();
}

'IT > 소스코드' 카테고리의 다른 글

[C/linux] TCP/IP 가위바위보 게임 (Concurrent Server Version)  (0) 2004/07/07
Intersecting Circles  (2) 2004/06/15
[C++] Orchard Trees  (0) 2004/06/04
[C++] Maximum Sum (upgrade)  (2) 2004/05/18
[C++] Maximum Sum  (0) 2004/05/10
[C] AVL Tree  (0) 2003/10/16
Posted by zzun

Trackback Address :: http://zzun.net/trackback/682 관련글 쓰기

댓글을 달아 주세요

[info]
http://acm.uva.es/p/v1/108.html
내림피아드 프로젝트의 첫번째 문제
O(N^3) 알고리즘

[test.in]
4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1
8 0 -2

[n01_zzun.cpp]
/**

Max-Sum Subrectangle Search

zzun
http://zzun.net
hello82@unitel.co.kr

**/

#include <iostream.h>
#include <fstream.h>
#include <stdio.h>
#include <stdlib.h>

int array_size;
char** num_array;

bool read_input(char* filename)
{
       ifstream fin;
       int buf;

       fin.open( filename );

       fin >> array_size;        // take the array size N
       if ( array_size <= 0 )
       {
               cout << "Error : array size!" << endl;
               return false;
       }

       num_array = new char*[array_size];
       for (int i=0; i<array_size; i++)
               num_array[i] = new char[array_size];        // 2-dim array M-allocate

       for (int i=0; i<array_size; i++)
               for (int j=0; j<array_size; j++)
               {
                       fin >> buf;
                       num_array[i][j] = (char) buf;        // take the values
               }
       
       fin.close();

       return true;
}

int main()
{
       char* input_filename;
       int** sum;
       int max = 1 << 31;
       int local_max, local_max_candi, temp;

       input_filename = "test.in";        

       if ( !read_input(input_filename) )
               return -1;

       sum = new int*[array_size+1];        // 2-dim array for SUM from [0,0] to [x,y]
       for (int i=0; i<array_size+1; i++)
       {
               sum[i] = new int[array_size+1];
               sum[i]++;        // move the pointer to use the -1 index
       }
       sum++;        // move higher pointer too, so we can use sum[-1 ~ array_size][-1 ~ array_size]

       for (int i=-1; i<array_size; i++)
       {
               sum[i][-1] = 0;
               sum[-1][i] = 0;        // init
       }

       for (int i=0; i<array_size*2-1; i++)
               for (int j=0; j<=i; j++)
                       if ( i-j < array_size && j < array_size )
                               sum[j][i-j] = num_array[j][i-j] + sum[j-1][i-j] + sum[j][i-j-1] - sum[j-1][i-j-1];        // calculate sum[][], O(N^2)

       for (int i=0; i<array_size; i++)
               for (int k=0; k<=i; k++)
               {
                       local_max = 1 << 31;
                       local_max_candi = 0;
                       for (int j=0; j<array_size; j++)
                       {
                               temp = sum[i][j] - sum[i][j-1] - sum[k-1][j] + sum[k-1][j-1];
                               local_max_candi += temp;
                               if ( temp > local_max && temp > local_max_candi )
                                       local_max = local_max_candi = temp;
                               else if ( local_max_candi > local_max )
                                       local_max = local_max_candi;
                               else if ( temp > local_max_candi )
                                       local_max_candi = temp;
                       }
                       max = (local_max > max) ? local_max : max;
               }

       cout << max << endl;

       sum--;
       for (int i=0; i<array_size+1; i++)
       {
               sum[i]--;
               delete [] sum[i];
       }
       delete [] sum;        // M de-alloc

       return 0;
}

'IT > 소스코드' 카테고리의 다른 글

Intersecting Circles  (2) 2004/06/15
[C++] Orchard Trees  (0) 2004/06/04
[C++] Maximum Sum (upgrade)  (2) 2004/05/18
[C++] Maximum Sum  (0) 2004/05/10
[C] AVL Tree  (0) 2003/10/16
[C] fork(), exec(), and wait()  (0) 2003/10/16
Posted by zzun

Trackback Address :: http://zzun.net/trackback/681 관련글 쓰기

댓글을 달아 주세요

  1. zzun 2004/05/19 03:19 Address Modify/Delete Reply

    우선 1차원 행렬에서 maxsum substring을 O(N)에 구하는 알고리즘

    a1, a2, ..., ax, ..., ay, ay+1, ..., ak-1, ak, ...
    이런 행렬이 있다고 치고,
    a1~ak-1 중에 maxsum substring을 ax...ay 라고 하자.

    그렇다면 위의 조건을 이용하여 a1~ak의 maxsum substring을 O(1) 안에 구할 수 있으면
    귀납법으로 전체의 maxsum substring을 O(N) 안에 구할 수 있게된다.

    a1~ak의 maxsum substring이 될 수 있는 후보는,
    1. a1~ak-1의 최대값인 ax...ay : max
    2. 새로운 원소 하나 ak
    3. 또 다른 스트링 az...ak (단, x<=z<k) : candi
    위에서 1번과 3번을 편의상 max랑 candi라고 부르자.

    여기서 candi 값을 잘 유지하는게 중요한데
    임의의 점부터 현재원소까지의 합 중 maximum 값을 유지해야 한다.
    (즉, ak를 끝점으로 하는 substring 중에 max를 말한다.)

    위의 과정을 하는 코드를 짜보면..


    max = -inf; candi=0;
    for k=1 to k=N
    {
    candi += ak
    if ( ak > max && ak > candi )
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = candi = ak; // 위에서 2번 후보에 해당
    else if ( candi > max )
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max = candi;&nbsp;&nbsp;// 위에서 3번 후보에 해당
    else if ( ak > candi )
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;candi = ak; // candi를 최신으로 유지하기 위한 코드
    } // 위에서 1번 후보의 경우는 max값을 갱신할 필요 없음
    print max;



    이래서 1차원 행렬의 max를 O(N) 만에 구할 수 있다.

    이것을 2차원에 적용하는 방법은
    사각형의 네 좌표를 [,]-[,] 식으로 나타낸다면
    [0,a]-[0,b] (a,b는 임의의 수) 같은 사각형은 총 O(N^2)개 존재한다.
    이 각 사각형들 내부의 합은 우리가 N^4할때 썼던 방법으로 쉽게 구하고
    이 사각형 중 maximum은 위에서 언급한 1차원 알고리즘으로 구할 수 있다.
    즉, O(N) 시간안에 최대값을 구할 수 있다는 얘기다.
    이런 방법으로 [0,a]-[1,b] 의 최대값, [2,a]-[5,b] 의 최대값
    식으로 구하면
    총 O(N^2)개의 최대값을 O(N^3) 시간 안에 구할 수 있고
    그 모든 최대값 중에 최대값이 바로 우리가 원하는 값이다.

  2. 2004/05/22 19:22 Address Modify/Delete Reply

    좀 퍼갈께..ㅋㅋ

[C++] Maximum Sum

IT/소스코드 2004/05/10 04:09 |
[info]
http://acm.uva.es/p/v1/108.html
내림피아드 프로젝트의 첫번째 문제
O(N^4) 알고리즘

[test.in]
4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1
8 0 -2

[n01_zzun.cpp]
/**

Max-Sum Subrectangle Search

zzun
http://zzun.net
hello82@unitel.co.kr

**/

#include
#include
#include
#include

int array_size;
char** num_array;

bool read_input(char* filename)
{
       ifstream fin;
       int buf;

       fin.open( filename );

       fin >> array_size;        // take the array size N
       if ( array_size <=>               return false;
       }

       num_array = new char*[array_size];
       for (int i=0; i<array_size; i++)
               num_array[i] = new char[array_size];        // 2-dim array M-allocate

       for (int i=0; i<array_size; i++)
               for (int j=0; j<array_size; j++)
               {
                       fin >> buf;
                       num_array[i][j] = (char) buf;        // take the values
               }
       
       fin.close();

       return true;
}

int main()
{
       char* input_filename;
       int** sum;
       int max = 1 << 31;
       int temp;

       input_filename = "test.in";        

       if ( !read_input(input_filename) )
               return -1;

       sum = new int*[array_size+1];        // 2-dim array for SUM from [0,0] to [x,y]
       for (int i=0; i<array_size+1; i++)
       {
               sum[i] = new int[array_size+1];
               sum[i]++;        // move the pointer to use the -1 index
       }
       sum++;        // move higher pointer too, so we can use sum[-1 ~ array_size][-1 ~ array_size]

       for (int i=-1; i<array_size; i++)
       {
               sum[i][-1] = 0;
               sum[-1][i] = 0;        // init
       }

       for (int i=0; i<array_size*2-1; i++)
               for (int j=0; j<=i; j++)
                       if ( i-j < array_size && j < array_size )
                               sum[j][i-j] = num_array[j][i-j] + sum[j-1][i-j] + sum[j][i-j-1] - sum[j-1][i-j-1];        // calculate sum[][], O(N^2)

       for (int i=0; i<array_size; i++)
               for (int j=0; j<array_size; j++)
                       for (int k=0; k<=i; k++)
                               for (int l=0; l<=j; l++)
                               {
                                       temp = sum[i][j] - sum[i][l-1] - sum[k-1][j] + sum[k-1][l-1];        // calculate sum of subrectangle, O(N^4)
                                       if ( temp > max )
                                               max = temp;
                               }

       cout << max << endl;

       sum--;
       for (int i=0; i<array_size+1; i++)
       {
               sum[i]--;
               delete [] sum[i];
       }
       delete [] sum;        // M de-alloc

       return 0;
}

'IT > 소스코드' 카테고리의 다른 글

[C++] Orchard Trees  (0) 2004/06/04
[C++] Maximum Sum (upgrade)  (2) 2004/05/18
[C++] Maximum Sum  (0) 2004/05/10
[C] AVL Tree  (0) 2003/10/16
[C] fork(), exec(), and wait()  (0) 2003/10/16
[C] Binary Search Tree  (0) 2003/10/11
Posted by zzun

Trackback Address :: http://zzun.net/trackback/680 관련글 쓰기

댓글을 달아 주세요

프로그래밍 언어 / 2003년 1학기 / 한상영 교수님

[설명]
2차원에서의 15-puzzle을 3차원으로 확장한 개념.
임의의 퍼즐 배치를 입력으로 받아
Optimal Solution(최소move)을 구함.
Cell을 움직이거나, 움직임의 sequence를 입력받아 움직일 수 있음.

[puzzle.cpp]
#include <iostream.h>
#include <fstream.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#define WIDTH 4

short CELL[WIDTH][WIDTH][WIDTH];
short* CELL_S = &(CELL[0][0][0]);                // the 1-dimension alias of the 3-dimension array CELL
short MD[WIDTH*WIDTH*WIDTH][WIDTH*WIDTH*WIDTH];                        // save All possible MD values.
short ANS[1000] = {0};                                        // the optimal solution of minimum moving sequence
int bound;

bool read_input(char* filename)                        // at first, load input file (ex. from puzzle.in)
{
       ifstream in (filename);
       
       char buf;
       int current_cell = 0;
       int counter = 0;

       while (in.get(buf))
       {
               if (buf>='0' && buf<='9')
               {
                       current_cell = current_cell*10 + (buf - '0');
               }
               else if (buf == '$')
                       current_cell = 64;
               else
               {
                       if (current_cell > 64)
                       {
                               cout << "ERROR : Wrong input file." << endl;
                               return false;
                       }
                       else if (current_cell > 0)
                       {
                               CELL_S[counter] = current_cell;                        // save it in to the array
                               counter++;
                               current_cell = 0;
                       }
               }                                
       }

       in.close();

       int inv_count = 0;                        // Check whether this problem can be solved or not

       for (int i=1; i<WIDTH*WIDTH*WIDTH; i++)
       {
               if (CELL_S[i-1]>CELL_S[i])
                       inv_count++;
       }

       if (inv_count%2 == 0)
       {
               cout << "Impossible to solve!" << endl;
               return false;
       }

       return true;
}

void set_md()                                // compute Manhattan Distance of all possible pair of cells
{
       int i_x, i_y, i_z, j_x, j_y, j_z;

   for (int i=0; i<WIDTH*WIDTH*WIDTH; i++)
       {
               i_x = i % WIDTH;
               i_z = i / (WIDTH*WIDTH);
               i_y = (i - i_z*WIDTH*WIDTH) / WIDTH;
               for (int j=0; j<WIDTH*WIDTH*WIDTH; j++)
               {
                       j_x = j % WIDTH;
                       j_z = j / (WIDTH*WIDTH);
                       j_y = (j - j_z*WIDTH*WIDTH) / WIDTH;
                       
                       MD[i][j] = abs(i_x - j_x) + abs(i_y - j_y) + abs(i_z - j_z);                // |x1-x2| + |y1-y2| + |z1-z2|
               }
       }

       return;
}

int cur_MD()                                // return current sum of MDs
{
       int md = 0;

       for (int i=0; i<WIDTH*WIDTH*WIDTH; i++)
       {
               if (CELL_S[i] == 64)
                       continue;
               md += MD[i][CELL_S[i]-1];
       }

       return md;
}

bool move_to(int dir)                // move to dir
{
       int x, y, z, idx;                                // find the empty cell
       for (idx=0; idx<WIDTH*WIDTH*WIDTH; idx++)
               if (CELL_S[idx]==64) break;
       x = idx % WIDTH;
       z = idx / (WIDTH*WIDTH);
       y = (idx - z*WIDTH*WIDTH) / WIDTH;

       switch (dir)
       {
       case 1 :                                                // move up
               if (y != 0)
               {
                       CELL[z][y][x] = CELL[z][y-1][x];
                       CELL[z][y-1][x] = 64;
               }
               else
                       return false;                        // impossible to move
               break;

       case 2 :                                                // move down
               if (y != 3)
               {
                       CELL[z][y][x] = CELL[z][y+1][x];
                       CELL[z][y+1][x] = 64;
               }
               else                        
                       return false;
               break;
       
       case 3 :                                                // move left
               if (x != 0)
               {
                       CELL[z][y][x] = CELL[z][y][x-1];
                       CELL[z][y][x-1] = 64;
               }
               else
           return false;
               break;
       
       case 4 :                                                // move right
               if (x != 3)
               {
                       CELL[z][y][x] = CELL[z][y][x+1];
                       CELL[z][y][x+1] = 64;                        
               }
               else
           return false;
               break;

       case 5 :                                                // move forward
               if (z != 0)
               {
                       CELL[z][y][x] = CELL[z-1][y][x];
                       CELL[z-1][y][x] = 64;
               }
               else
           return false;        
               break;

       case 6 :                                                // move backward
               if (z != 3)
               {
                       CELL[z][y][x] = CELL[z+1][y][x];
                       CELL[z+1][y][x] = 64;                        
               }
               else
                       return false;
               break;
       
       default :
               return false;
       }

       return true;                                        // success to move
}

bool IDA(int depth, short prev)                // searching algorithm
{
       depth++;
       short opp;

       for (int i=1; i<=6; i++)
       {
               opp = (i%2 == 0) ? i-1 : i+1;                // the opposite side of moving direction.
               if (prev != opp && move_to(i))
               {
                       if (cur_MD()+depth<=bound)
                       {
                               if (depth == bound || IDA(depth, i))                // recursive call
                               {
                                       move_to(opp);                        // move back
                                       ANS[depth] = i;                        // save the answer
                                       return true;
                               }
                       }
                       move_to(opp);                        // move back
               }
       }

       return false;
}

void print_cur()                                        // print out the current status
{
       for (int i=0; i<WIDTH; i++)
       {
               for (int j=0; j<WIDTH; j++)
               {
                       for (int k=0; k<WIDTH; k++)
                       {
                               if (CELL[j][i][k] == 64)
                                       printf("  $");
                               else
                   printf("%3d", CELL[j][i][k]);
                       }
                       printf(" | ");
               }
               printf("\n");
       }
       return;
}

void search()                                                // find the optimal solution
{
       bound = cur_MD();                                // lower bound of moves in optimal solution

       if (bound != 0)
       {
               cout << "Lower Bound = " << bound << endl << "Now Searching..." << endl;

               cout << "Trying " << bound << endl;

       while(!IDA(0, -1))                        // searching start
               {
                       bound += 2;                                // if the solution wasn't found, try with bound+2 as the lower bound
                       cout << "Trying " << bound << endl;
               }

               cout << "Success!" << endl;
       }

       return;
}

int main(int argc, char* argv[])
{
       char *input_file, *output_file;//, *cmd;

       /*if (argc != 2)                                                // check the arguments
       {
               printf("ERROR : Please enter the input file name as an argument.\n");
               return 1;
       }*/

       input_file = "puzzle.in";//argv[1];

       if (!read_input(input_file))                // read the input file and save it into the array
               return 1;

       char cmd[20];
       //cmd = new char[20];

       set_md();                                                        // set the MD values

       print_cur();

       printf("$>");
       cin.getline(cmd, sizeof(cmd));                                // ready to accept a command

       while (strcmp("quit", cmd))
       {
               if (strlen(cmd)==1 && cmd[0] >= '1' && cmd[0] <= '6')                        // moving command
               {
                       if(!move_to((int)(cmd[0] - '0')))
                               cout << "Illegal Move!" << endl;                        // fail to move
                       else
                               print_cur();                                                                // success to move
               }
               else if (!strncmp("in ", cmd, 3))                        // read a sequence from a file
               {
                       char buf;
                       input_file = cmd + 3;
                       ifstream in(input_file);
                       cout << "Moving... : ";
                       while(in.get(buf))
                       {
                               if (buf >= '1' && buf <= '6')
                               {
                                       cout << buf;
                                       if(!move_to((int)(buf - '0')))
                                       {
                                               cout << " Illegal Move!" << endl;
                                               goto exit;
                                       }
                               }
                       }

                       exit :
                       in.close();
                       cout << endl;
                       print_cur();
               }
               else if (!strncmp("out ", cmd, 4))                        // solve the puzzle, and put out the optimal sequence of moves
               {
                       output_file = cmd + 4;
           search();
                       cout << "Optimal solution : " << bound << " moves." << endl;
                       ofstream out(output_file);
                       for (int i=1; ANS[i] != 0; i++)                        // ANS re-initialization for next solving
                       {
                               out << ANS[i];
                               ANS[i] = 0;
                               if (i%10 == 0)
                                       out << endl;
                       }
                       out.close();

                       print_cur();
               }
               else
                       printf("Wrong Command.\n");

               printf("$>");
               cin.getline(cmd, sizeof(cmd));
       }

       return 0;
}

'IT > 소스코드' 카테고리의 다른 글

[MIT Scheme] Calculator  (0) 2003/07/10
[Java] Soma Cube  (0) 2003/07/10
[C++] 3-dimension 63-Puzzle  (1) 2003/07/10
[C++] Booth's Algorithm Simulator  (0) 2003/07/10
[MIPS Assembly] MAXMIN  (0) 2003/07/10
[MIPS Assembly] WriteBackwards  (0) 2003/07/10
Posted by zzun

Trackback Address :: http://zzun.net/trackback/666 관련글 쓰기

댓글을 달아 주세요

  1. zzun 2004/07/11 02:06 Address Modify/Delete Reply

    슬라이딩 퍼즐은 기본적으로 state들로 볼 수 있다.
    15-puzzle의 경우엔 총 16!개의 state가 존재하고
    그 state들이 서로 얽히고 &#49445;히도록 transition이 존재한다.

    초기의 생각은 그런 state들을 그룹지어서..
    각 transition에게 특성을 부여하는거였는데..
    워낙 광범위하고, 정의하기가 어려워서 포기했다.
    그러던 중 IDA* 알고리즘을 발견하게 됐고,
    트리 형태로 구현하는 방법을 생각하게 됐다.

    16!개의 state로 생각하지 말고...
    현재의 state를 root로 두고...
    모든 state는 child를 4개(4방향으로 움직일 수 있음, 실제론 3개-왔던방향으로 돌아가는건 의미없으므로)씩 갖고 있는 node라고 생각하면...
    무한히 뻗어나갈 수 있는 트리를 생각할 수 있다.

    이렇게 되면 transition은 아주 일반적인 것이 되므로..
    각 node를 특성화 시키는게 필요한데
    가장 간단한것이 node마다 어떤 숫자를 부여하는 것이다.
    GOAL state로 부터 얼마나 떨어져있나 하는 숫자.

    이때 쓴것은 Manhattan Distance 라고...
    간단히 말해 |x1-x2| + |y1-y2| 를 구하는 것이다.
    현재 15개의 cell에 대해 MD들을 다 합하면(empty cell 제외)
    일정한 값이 되고 이 값이 각 state를 구분짓는 기준이 된다.
    또한, 현재 state의 MD의 합은 곧 optimal solution의 move수의 lower bound가 된다.
    (한번의 move에 반드시 하나의 cell이 empty cell과 바뀌므로)

    이제 tree를 타고 내려가면서 검색을 시작한다.
    tree라고 해서 직접 구현하는것이 아니라
    recursive function을 통해 간단히 구현한다.
    empty cell이 이동 가능한 지점들을 차례로 방문하면서
    만약 그 지점으로 이동했을경우 MD+depth가 구해놓은 lower bound보다 작거나 같다면 제대로 찾아온 것이므로 검색을 계속한다(recursive call).
    크다면 잘못 온것이므로 false를 return하면서 이동한것을 원래대로 복귀시킨다.

    이렇게 검색을 하다가 MD = 0 이 되고 현재 node의 tree depth가 lower bound랑 같다면 해를 구한 것이 된다. 이 때는 true를 return하면서 구했던 solution을 저장한다.

    만약 lower bound에 해당하는 모든 solution을 검색했으나 딱 떨어지는 solution이 없을 경우엔 lower bound를 2만큼 증가시켜 다시 검색을 시도한다.
    (bound를 1 증가시키는건 의미가 없다.)

    이번 숙제는 3차원 63-puzzle 이였는데
    간단한 확장으로 어렵지 않게 구현이 가능하다.

컴퓨터 구조 / 2003년 1학기 / 김지홍 교수님

Booth's Algorithm을 이용한 Low Level적인 곱셈을 시뮬레이션

/*************************************************************************
**                                                                    **
**                Assignment 3. 1번 Booth's algorithm simulator                    **
**                                                                    **
**                ca49 2001-12204 이준희                                    **
**                                                                    **
*************************************************************************/

#include <stdlib.h>
#include <string.h>
#include <iostream.h>
#include <stdio.h>
#include <math.h>

void printHex(int hex)                        // int를 16진수 형식으로 출력하는 함수
{
       if (hex < 0)
               printf("0x%X", hex);                                // 음수이면, %X로 그냥 출력
       else if (hex == 0)
               printf("0x00000000");                                // 0이면 0을 출력
       else
       {
               printf("0x");
               for (int i=7; pow(16, i) > hex; i--)              // 양수이면, 그만큼 0을 앞에 출력
                       printf("0");
               printf("%X", hex);
       }
       return;
}

void booth(int mcand, int mlier, int* p)                                // 실제 곱하기를 하는 함수
{
       long long int product;                                // 64비트 정수. hi+lo 의 역할
       int prev = 0;                                        // 이전bit. 현재는 phantom zero.
       int count = 0;
       int output;                                                // for 출력

       product = mlier;                                        // product의 초기값은 multiplier

       for (int i=1; i<33; i++)
       {
               product += ((prev - (product & 1)) * mcand) << 32;        
                            // product의 상위 32bit에 [ (이전bit - 지금bit) * multilicand ] 를 더합니다.
               prev = (int)product & 1;                        // shift 하기 전에, 이전bit에 현재bit을 저장.
               product >>= 1;                                // 오른쪽 shift
               output = (mcand*output < 0) ? (product + 1) : product;
                           // 출력값이 음수일 경우 2's complement 표현을 위해 조정.
               
               if (p[count] == i)                // 출력해야하는 번째의 iteration일 경우 출력!
               {
                       printf("%dth iteration: current_product = ", i);
                       printHex(output);
                       printf(" (%d in decimal notation)\n", output);
                       p[count] = 0;
                       count++;
               }
       }

       printf("Final product = ");                                // Final product 출력!
       printHex(output);
       printf(" (%d in decimal notation)\n", output);
}

int main(int argc, char* argv[])
{
       int a, b;
       int p[32] = {0};

       if (argc < 5)                                        // argument 개수 검사
       {
               cout << "Error : The Number of argument is illegal." << endl;
               return 1;
       }

       int count = 0;

       for (int i=1; i<argc; i+=2)
       {
               if (!strcmp(argv[i], "-a"))
                       a = atoi(argv[i+1]);
               else if (!strcmp(argv[i], "-b"))
                       b = atoi(argv[i+1]);
               else if (!strcmp(argv[i], "-p"))
               {
                       p[count] = atoi(argv[i+1]);
                       count++;                        // 몇 번째의 iteration을 출력해야하는지 저장
               }
               else
               {
                       cout << "Error : Arguments is illegal." << endl;
                       return 1;
               }
       }

       printf("A : ");
       printHex(a);
       printf("\nB : ");
       printHex(b);
       printf("\n");                                                // A, B 출력

       booth(a, b, p);
       a = b = count = 0;

       char command[50] = {0};
       char seps[]   = " \t";                        // 입력받은 커맨드를 토큰으로 자를 기준
       char *token, *next;

       printf("(Booth) ");
       fgets(command, 50, stdin);

       while (strncmp(command, "exit", 4))
       {
               token = strtok( command, seps );
               next = strtok( NULL, seps );                        // 한번에 2개의 토큰을 읽음
               while( (token != NULL) && (next != NULL) )
               {
                       if (!strcmp(token, "-a"))
                               a = atoi(next);
                       else if (!strcmp(token, "-b"))
                               b = atoi(next);
                       else if (!strcmp(token, "-p"))
                       {
                               p[count] = atoi(next);
                               count++;
                       }
                       else
                       {
                               cout << "Error : Arguments is illegal." << endl;
                               return 1;
                       }

                       token = strtok( NULL, seps );
                       next = strtok( NULL, seps );
               }

               printf("A : ");
               printHex(a);
               printf("\nB : ");
               printHex(b);
               printf("\n");                                        // A, B 출력

               booth(a, b, p);
               a = b = count = 0;

               printf("(Booth) ");
               fgets(command, 50, stdin);
       }

       return 0;
}

'IT > 소스코드' 카테고리의 다른 글

[Java] Soma Cube  (0) 2003/07/10
[C++] 3-dimension 63-Puzzle  (1) 2003/07/10
[C++] Booth's Algorithm Simulator  (0) 2003/07/10
[MIPS Assembly] MAXMIN  (0) 2003/07/10
[MIPS Assembly] WriteBackwards  (0) 2003/07/10
[MIPS Assembly] Quicksort  (0) 2003/07/10
Posted by zzun

Trackback Address :: http://zzun.net/trackback/665 관련글 쓰기

댓글을 달아 주세요