'전체 글'에 해당되는 글 203건

  1. 2015.04.14 더블릿_스위치상태
  2. 2015.04.14 더블릿_짧은노래
  3. 2015.04.09 면접알고리즘시그_1주차
  4. 2015.04.09 2670_연속부분최대곱
  5. 2015.04.09 2668_숫자고르기

문제정리)

스위치개수와 현재 스위치 상태가 입력

학생수가 입력되고 

각 학생마다 학생성별, 학생번호가 입력됨

남자와 같은 경우에는 

학생번호의 배수의 인덱스를 가지는 스위치를 상태 전환

여자와 같은 경우에는

학생번호를 기준으로 좌우 대칭 되는 최대 범위만큼 스위치를 상태 전환


문제 풀이)

남학생은 반복문 수행하면서 자신의 인덱스로 나누어서 나머지가 0이면 그러니까 나누어 떨어지는 인덱스를

상태 변환시켜주면 된다. (i % 학생번호 == 0)

여학생이 조금 당황 스러웠는데,

좌우 대칭의 범위를 count변수로 관리하면서 하나씩 늘려나가면서 대칭되면 while문을 계속 수행하게 했고, 

대칭 되지 않으면 while문을 빠져나오게했다.

한 가지 예외는 범위를 늘리다가 할당된 배열의 범위를 넘어서는 경우가 있을 것이라고 판단했다. 

좌우대칭범위를 설정하는데, (count가 학생번호보다 커지면) 배열 인덱스가 음수가 되기 때문에 종료해야 한다.

count가 (전체 스위치 개수 - 학생번호보다 커지면) 할당된 스위치 개수 이상의 인덱스에 접근하기 때문에 종료해야 한다.


이 부분만 잘 처리해주면 크게 문제 없이 수행하는 코드가 완성

'알고리즘문제풀이' 카테고리의 다른 글

더블릿_어망투망  (0) 2015.04.14
더블릿_종이 자르기(소트)  (0) 2015.04.14
더블릿_짧은노래  (0) 2015.04.14
면접알고리즘시그_1주차  (0) 2015.04.09
2670_연속부분최대곱  (0) 2015.04.09
Posted by slender ankles
,

문제가 길다고 어려운 것은 아니다. 차근차근 읽어보고 해결책을 찾아보면

대개 긴 문제들이 오히려 쉬울 가능성이 높다는 것을 느낀다.

악보 (1<=N<=10000)개, 각 악 보당 비트(0<=bi<=120)의 정보가 주어진다. 

처음에는 2차원 배열을 쓰는 문제인가 생각하다가 

손으로 그려보면서 풀어보니 1차원 배열로 푸는 것이 답을 구하는데 더 좋다고 판단했다. 

1차원 배열의 범위는 10000 * 120 => 1200000

백이십만개 정도면 된다. 

악보의 비트 정보가 주어지면 

그 해당 배열에 악보넘버를 저장해주는 식으로 입력을 구성했다. 

for(악보범위 i)

while()

       arr[전역변수로 관리하는 인덱스, 곧 시간] = i(악보번호)

로 저장해주면 

ques가 날라왔을 때(시간) 바로 인덱스로 접근해서 답을 도출해내면 된다.

'알고리즘문제풀이' 카테고리의 다른 글

더블릿_종이 자르기(소트)  (0) 2015.04.14
더블릿_스위치상태  (0) 2015.04.14
면접알고리즘시그_1주차  (0) 2015.04.09
2670_연속부분최대곱  (0) 2015.04.09
2668_숫자고르기  (0) 2015.04.09
Posted by slender ankles
,

더블릿_더큰

쫌 고민을 많이 했다. 

우선 문제를 간단히 정리하자면

1<= x <= 999999 의 숫자가 입력되면

이 수에 포함되어 있는 숫자들을 이용하여 만든 수들 중에 입력된 수보다 큰 최소수를 구하는 문제이다.

다소 문제 설명이 어렵지만,

156을 보자면 156이 포함되어 있는, 156의 자리수로 만들 수 있는 숫자는

156, 165, 516, 561, 615, 651 등등이 있다. 

이 중 입력된 156보다 큰 최소 수는 165이다.


문제 풀이)

처음에는 어떻게 풀어야 되나 굉장히 고민을 많이 했다. 156의 자리수를 가지고 만들 수 있는 수들을 다 구한다음에 정렬하고, 

입력받은 수 보다 큰 숫자를 출력해야 되나? 가 첫 번째 떠오른 방법이었다. 일단 1~999999이기 때문에 숫자를 만드는 방법에 대해서 어려운 점이 있었다.

한번 더 생각해보니까 

1~999999까지 for문을 돌리면서 조건을 만족시키는 숫자를 캐치해내면 되겠다고 생각했다. 

예를 들어 156이 입력되면

1) 156~999999까지 반복문을 수행한다.

2) 각 숫자들마다 자리 수에 있는 숫자들을 판별하여 1,5,6에 부합한지를 체크한다.

3) 만약 조건에 부합하면 바로 출력하고 프로그램을 끝낸다.

4) 조건에 부합하지 않으면 0을 출력한다.


더블릿_빙고

1)나의 빙고판을 입력받는다.

2)사회자가 부르는 번호를 입력받는다.

3) 사회자가 입력되는 순서대로 내 빙고를 체크해준다.

** 빙고를 판별하는 것은 

// 대각선

[x][y] 좌표가 x == y일때와, x + y = 6일 때

// 가로

[x][y] 좌표가 x는 고정시키고 y를 1~5까지 순회

// 세로

[x][y]좌표가 y는 고정시키고 x를 1~5까지 순회


더블릿_wrap around

정말 느낀점이 많은 문제이다.

10*10 배열이 주어지고 상, 하, 좌, 우, 대각선의 5개의 합을 도출해내는 문제였다. 

정말 쉽다고 생각했다. 

현재 인덱스에서 +0, +1, +2, +3, +4 해주면서 그 값을 %10해주면 10을 넘어가도 인덱스가 순환할 수 있게 되어

원하는 답을 구할 수 있게 된다. 

그런데 내가 음수가 되는 부분에 대해서 예외처리를 안해주었다. ㅜㅜ 근데 황당한 것은 비주얼 스튜디오에서는 쓰레기값에 대한 처리가 리눅스와 달라서 답이 제대로 나오는데 제출되는 컴파일러에서는 그렇지 않아서 문제점을 찾는데 애를 먹었다.

다시 한 번 말하지만 로직을 짜기 전에 한 번 손으로 그려보고 맞춰보는 형태가 정말 중요하다는 것을 알았다. 

결국 인덱스를 좌로 가거나 상으로 가는 연산에서는 행에서 -1, -2, -3, -4해줄 때 원래 인덱스에서 10을 더해준다음에 연산을 수행해주면 아무 문제가 없다. 


더블릿_폭탄게임

행, 열 정보가 주어진다. A는 폭탄을 어느 한점에 숨겨둔다.

B는 폭탄을 떨어뜨려 보면서 A가 놓은 폭탄의 위치를 알아맞추는 문제였다.

처음은 굉장히 간단한 문제라고 생각하면서 풀어보다가 낭패를 맛 보았따.

반드시 예제의 테스트케이스를 손으로 돌려보면서 내 로직이 정확한 답을 내놓는지를 검사해봐야

시간 낭비를 줄일 수 있다고 깨달았다. 

처음에는 그냥 간단히 폭탄이 떨어지는 위치를 bool 배열을 이용해서 true false를 갱신해준 다음에 true인 배열의 개수를 통해

답이 도출되는 줄 알았따. 

그런데 폭탄을 떨어뜨릴 때마다 가장 최신의 정보를 가지고 점점 폭탄의 범위를 좁혀나가야 하는 문제였다. 


문제를 풀면서 몇 가지 이슈에 대해서 설명해 보자면

1) 폭탄의 범위를 설정하는 부분이다. 

어느 한 점 x, y가 주어지고 폭탄의 범위는 p(홀수)가 주어진다. 

손으로 대충 그려보니 폭탄의 범위를 설정해주기 위해서는

x - (p - 1) / 2  ~  x + (p - 1)/2 로 설정

y - (p - 1)/ 2  ~ y + (p - 1)/2로 설정

해주면 정확한 정사각형의 범위의 폭탄을 설정해줄 수 있다. 

그리고 폭탄의 위치는 단 한개이므로 폭탄이 떨어질 때마다 그 값들을 점차 증가시켜주면서 

마지막에 가장 많이 겹치는 부분을 답으로 도출해주었더니 답을 구할 수 있었다.


더블릿_계단오르기

문제정리) 

계단은 한 칸 오를 수 있고, 두 칸을 오를 수 있다. 

입력받은 계단까지 오르는 경우의 수를 출력하라

라는 것이 문제였다.

풀이정리)

재귀함수를 작성하는 것에 대한 좋은 연습문제였던 거 같다. 

항상 재귀함수에 대해서 정확히 어떤 메커니즘을 가지는 것인가에 대해서 많은 생각을 해보게 된다. 

좀 더 연습을 해야 겠지만 많은 문제를 풀어보면서 재귀에 대해서 알 필요가 있을 것 같다.

여태껏 느낀 것은 좋은 점화식을 통해서 답을 구해 낼 수 있다는 것이다. 

입력의 4번째 계단까지 오르는 경우의 수를 간단히 생각해보면

4번째 계단까지 오르는 경우의 수는 3칸까지 올라와서 1칸을 오르는 경우와 2칸까지 올라와서 2칸을 오르는 경우의 합이다.

대충 손으로 그려봐도 정확한 점화식을 구하기가 어려웠는데 이 부분에 대해서는 좀 더 연습을 통해 명확한 매커니즘을 

구축해야 될 필요가 있을 것 같다. 

너무 전형적인 문제여서 생각도 하기 전에 답이 떠오르는 문제였다. 


더블릿_비트패턴

재귀함수를 사용하는 문제에서는 언제나 어려움을 겪는다. 재귀적인 탐색방법에 대한 기본적인 개념이 부족한 듯하다.

재귀함수의 탈출 조건은 1을 k번만큼 썼을 때 출력하고 끝내게 했다.

아니면 현재의 인덱스가 n보다 크게 되면 탈출하게 했다. 

그 외의 상황에서는 1또는0을 바꾸어가면서 재귀적인 수행을 하게끔 코딩해줬다.

풀고 나서도 어떻게 답을 도출해냈는지에 대해서 명확하게 설명을 하기가 애매한 상황이다. 

이 부분은 반드시 다시 짚고 넘어가야 할 부분 같다. 패턴을 만들어내는 것이 내가 반드시 해야될 일인 듯하다.

다시 풀어볼 때 참고하기 위한 소스코드

#include <iostream>
using namespace std;
 
int arr[31];
int n, k;
 
void bitpattern(int current_i, int use_one){
    if (use_one == k){
        for (int i = 1; i <= n; i++){
            cout << arr[i];
        }
        cout << endl;
        return;
    }
    if (current_i == n + 1return;
    arr[current_i] = 1;
    bitpattern(current_i + 1, use_one + 1);
    arr[current_i] = 0;
    bitpattern(current_i + 1, use_one);
}
 
int main(){
    cin >> n >> k;
    bitpattern(10);
    return 0;
}
 
cs


더블릿_십자카드

엄청난 오류에 빠졌다. 요즘 왜 이렇게 문제에 대해서 잘 못 파악하고 시간을 낭비한 적이 많은지 모르겠다.

일단 무조건 문제에 주어지는 것을 고대로 코드로 옮기는 방법을 먼저 시도해야 된다고 생각한다. 그 동안은 자의적인 해석으로 더 좋은 방법으로 간단하게 풀고자 노력했었다. 하지만 이 것은 아닌 듯 싶다. 

십자카드를 만족하는 수들이 a, b, c, d로 완전탐색을 하면서 

이렇게 조건을 걸어 주었는데 =====>>>>>  (a <= b && a <= c && c <= d)

이 것은 엄청 잘 못 된 방법이었다. 문제를 제대로 파악하지 못 한 케이스였다. ㅜㅜ 

무조건 십자카드는 십자카드에 있는 순서대로 글자를 바꾸어가면서 최소값을 찾아봐야 하는데, 위의 로직은 그렇지가 않는다. 

일단 처음에 몇 가지 숫자들을 써보니까 되길래 했는데 이 것이 낭패였다. 

아무튼 숫자 네 개를 순서대로 돌려가면서 최소값을 찾는 과정을 반드시 해줘야 한다. 

 maketencard라는 함수를 사용해서 최소값을 구해주고 그 최소값이 완전탐색시의 a * 1000 + b * 100 + c * 10 + d와 일치하면 십자카드를 만족하는 수라고 판단하고 카운트를 올려주었다. 그리고 입력받은 수와 동일한 값이 나오면 빠져나오게 하고 카운트를 출력해주는 방식으로 구현했다. 








'알고리즘문제풀이' 카테고리의 다른 글

더블릿_스위치상태  (0) 2015.04.14
더블릿_짧은노래  (0) 2015.04.14
2670_연속부분최대곱  (0) 2015.04.09
2668_숫자고르기  (0) 2015.04.09
더블릿_더큰  (0) 2015.04.08
Posted by slender ankles
,

어려운 문제인줄 알았는데 쉬운 문제였다.

우선 완전탐색부터 해봐야한다는 것을 알았다.

#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace std;
double arr[10001];
int n;
double maxvalue = -1;
void process(){
    for (int i = 0; i < n; i++){
        double sum = 1;
        for (int j = i; j < n; j++){
            sum *= arr[j];
            if (sum > maxvalue) maxvalue = sum;
        }
    }
}
int main(){
    cin >> n;
    for (int i = 0; i < n; i++){
        cin >> arr[i];
    }
    process();
    cout.setf(ios::fixed);
    cout.precision(3);
    cout << maxvalue << endl;
    return 0;
}
 
cs


DP로 푼 방법(참고)

#pragma warning(disable : 4996)
#include<stdio.h>
#include<iostream>
using namespace std;
 
double best,basic;
double data[10005];
int num,i,j;
 
int main(){
    cin >> num;
    for(i=0; i<num; i++){
        scanf("%lf",&data[i]);
    }
 
    best=basic=data[0];
 
    for(j=1; j<num; j++){
        if(data[j]>basic*data[j]){
            basic = data[j];
        }
        else{basic*=data[j];}
        if(basic > best){best = basic;}
    }
 
    printf("%.3lf",best);
    return 0;
}
 
cs



'알고리즘문제풀이' 카테고리의 다른 글

더블릿_짧은노래  (0) 2015.04.14
면접알고리즘시그_1주차  (0) 2015.04.09
2668_숫자고르기  (0) 2015.04.09
더블릿_더큰  (0) 2015.04.08
더블릿_계단오르기(dp)  (2) 2015.04.07
Posted by slender ankles
,

문제를 푸는데 쫌 오래 걸리고, 안타까웠다.

처음에 제대로 된 접근을 했는데, 이상한 생각을 중간에 섞어서 풀지 못했던 것이었다. 


문제 정리)

윗 줄의 번호를 몇 개 뽑아 그 번호들과 아래 번호들이 일치하는 경우를 뽑는 것인데 최대인 경우의 뽑으라는 문제였다.


풀이정리)

반복문을 수행하면서

해당하는 두번째 줄값으로 다시 위의 인덱스를 타고 들어가면서 

처음에 시작한 위치로 돌아오면 이 것은 문제의 경우를 만족하는 것이다.

재귀를 수행할때마다 그 값을 temp라는 배열에 저장하다가 만족하면 result라는 결과값을 모아놓는 배열에

넣어주었다. 물론 방문점 체크 처리도 해야 한다.

시간안에 풀지 못해서 아쉽다

'알고리즘문제풀이' 카테고리의 다른 글

면접알고리즘시그_1주차  (0) 2015.04.09
2670_연속부분최대곱  (0) 2015.04.09
더블릿_더큰  (0) 2015.04.08
더블릿_계단오르기(dp)  (2) 2015.04.07
더블릿_이진 검색  (0) 2015.04.06
Posted by slender ankles
,