반응형

문제 링크

 

algospot.com :: CLOCKSYNC

Synchronizing Clocks 문제 정보 문제 그림과 같이 4 x 4 개의 격자 형태로 배치된 16개의 시계가 있다. 이 시계들은 모두 12시, 3시, 6시, 혹은 9시를 가리키고 있다. 이 시계들이 모두 12시를 가리키도록

algospot.com

 

 

풀이 )

  0번 스위치를 시작으로 15번 스위치까지 각각 4번씩 눌러가면서 재귀호출을 통해서 모든 경우의 수에 대해서 탐색한다.

  전체 경우의 수가 4^10(10^6)이므로 시간초과가 나지 않는다.

 

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> push[10] = {
    {0, 1, 2},
    {3, 7, 9, 11},
    {4, 10, 14, 15},
    {0, 4, 5, 6, 7},
    {6, 7, 8, 10, 12},
    {0, 2, 14, 15},
    {3, 14, 15},
    {4, 5, 7, 14, 15},
    {1, 2, 3, 4, 5},
    {3, 4, 5, 9, 13}
};
int clocks[16];

int dfs(int num){
    if(num == 10){
        for(int i = 0; i < 16; ++i){
            if(clocks[i] != 12)
                return 1e7;
        }
        return 0;
    }

    int ret = 1e7;
    for(int i = 0; i < 4; ++i){
        ret = min(ret, i+dfs(num+1));
        int len = push[num].size();
        for(int i = 0; i < len; ++i){
            clocks[push[num][i]] = clocks[push[num][i]]%12+3;
        }
    }
    return ret;
}

int main(void){
    int c;
    cin >> c;
    while(c--){
        for(int i = 0; i < 16; ++i)
            cin >> clocks[i];

            int ans = dfs(0);
            if(ans >= 1e7)
                ans = -1;
            cout << ans << '\n';
    }
}
반응형

'문제풀이 > 알고스팟' 카테고리의 다른 글

[C++] 알고스팟 - BOARDCOVER  (0) 2020.12.28
[C++] 알고스팟 - PICNIC  (0) 2020.11.01
[C++] 알고스팟 - FESTIVAL  (0) 2020.03.09
반응형

문제 링크

 

algospot.com :: BOARDCOVER

게임판 덮기 문제 정보 문제 H*W 크기의 게임판이 있습니다. 게임판은 검은 칸과 흰 칸으로 구성된 격자 모양을 하고 있는데 이 중 모든 흰 칸을 3칸짜리 L자 모양의 블록으로 덮고 싶습니다. 이

algospot.com

 

풀이 )

  먼저 입력받은 '.'의 개수를 세서 3으로 나누어떨어지지 않는 경우 '0'을 출력하고 종료한다.

  '.'의 개수를 3으로 나누어 보드에 들어가는 총 블록의 수를 세고, DFS로 보드에 블록을 채워준다.

 

  DFS 함수 내에서는 기저사례로 남은 블록 수가 0일 때 1을 반환하게 한다.

  board에서 위에서부터 보면서 첫 '.'을 찾고, 그 위치에서 4종류의 블록을 넣어보면서 다음 블록을 채워 넣는다.

 

#include <iostream>
#include <string>

using namespace std;

int block[4][3][2] = {
    {{0, 0}, {1, 0}, {1, 1}},
    {{0, 0}, {0, 1}, {1, 1}},
    {{0, 0}, {1, 0}, {0, 1}},
    {{0, 0}, {1, 0}, {1, -1}}
};

int h, w;

int dfs(string board[], int numBlock){
    if(!numBlock)
        return 1;

    int x = -1, y = -1;
    for(int i = 0; i < h; ++i){
        for(int j = 0; j < w; ++j){
            if(board[i][j] == '.'){
                x = i;
                y = j;
                break;
            }
        }
        if(y != -1)
            break;
    }

    int ret = 0;
    for(int i = 0; i < 4; ++i){
        bool flag = 0;
        for(int j = 0; j < 3; ++j){
            int nx = x+block[i][j][0];
            int ny = y+block[i][j][1];
            if(nx < 0 || nx >= h || ny < 0 || ny >= w || board[nx][ny] == '#'){
                flag = true;
                break;
            }
        }
        if(flag)
            continue;

        for(int j = 0; j < 3; ++j){
            int nx = x+block[i][j][0];
            int ny = y+block[i][j][1];
            board[nx][ny] = '#';
        }
        ret += dfs(board, numBlock-1);
        for(int j = 0; j < 3; ++j){
            int nx = x+block[i][j][0];
            int ny = y+block[i][j][1];
            board[nx][ny] = '.';
        }
    }
    return ret;
}

int main(void){
    int c;
    cin >> c;
    while(c--){
        cin >> h >> w;
        string* board = new string[h];
        int numBlock = 0;
        for(int i = 0; i < h; ++i){
            cin >> board[i];
            for(int j = 0; j < w; ++j){
                if(board[i][j] == '.')
                    numBlock++;
            }
        }
        if(numBlock%3){
            cout << 0 << '\n';
            continue;
        }
        numBlock/=3;

        cout << dfs(board, numBlock) << '\n';
    }
}
반응형

'문제풀이 > 알고스팟' 카테고리의 다른 글

[C++] 알고스팟 - CLOCKSYNC  (0) 2020.12.28
[C++] 알고스팟 - PICNIC  (0) 2020.11.01
[C++] 알고스팟 - FESTIVAL  (0) 2020.03.09
반응형

문제 링크

 

algospot.com :: PICNIC

소풍 문제 정보 문제 안드로메다 유치원 익스프레스반에서는 다음 주에 율동공원으로 소풍을 갑니다. 원석 선생님은 소풍 때 학생들을 두 명씩 짝을 지어 행동하게 하려고 합니다. 그런데 서로

algospot.com

 

풀이 )

  짝이 되는 경우 사람이 2명씩 빠지게 되므로 남는 인원이 2명씩 줄게 되고 0명이 되는 경우 모두 짝을 이루기 때문에 답을 1 증가시킨다.

  친구 관계를 나타내는 2차원 배열과 이미 짝이 만들어졌는지 여부를 확인할 배열을 만들어서 아직 짝이 아니고 친구 관계인 2명의 친구를 짝으로 만들어주고 다른 모든 방법에 대해 확인해 보기 위해 재귀함수 호출 이후 반복문이 돌기 전에 짝으로 만들어진 부분을 지워준다.

 

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int c, n, m;
int rel[10][10];
int visited[10];
int ans;

void rec(int remain){
  if(remain == 0){
    ans++;
    return;
  }

  int first, second;
  for(int i = 0; i < n-1; ++i){
    for(int j = i+1; j < n; ++j){
      if(rel[i][j] && !visited[i] && !visited[j]){
        visited[i]++;
        visited[j]++;
        rec(remain-2);
        visited[i]--;
        visited[j]--;
      }
    }
  }
}

int fac(int num){
  if(num < 3)
    return num;
  return num * fac(num-1);
}

int main(void){

  cin >> c;
  while(c--){
    cin >> n >> m;
    ans = 0;
    fill(visited, visited+n, 0);
    for(int i = 0; i < n; ++i)
      fill(rel[i], rel[i]+n, 0);
    for(int i = 0; i < m; ++i){
      int first, second;
      cin >> first >> second;
      rel[first][second] = 1;
      rel[second][first] = 1;
    }

    rec(n);
    ans /= fac(n/2);
    cout << ans << endl;
  }
}

 

주의점 )

  • 재귀함수 속에서의 i와 j의 대소관계를 항상 유지하여 중복 제거
  • ans /= fac(n/2)을 통해 짝의 순서로 인해 생기는 중복 제거
반응형

'문제풀이 > 알고스팟' 카테고리의 다른 글

[C++] 알고스팟 - CLOCKSYNC  (0) 2020.12.28
[C++] 알고스팟 - BOARDCOVER  (0) 2020.12.28
[C++] 알고스팟 - FESTIVAL  (0) 2020.03.09
반응형

문제 링크

 

algospot.com :: FESTIVAL

록 페스티벌 문제 정보 문제 커다란 공연장을 빌려서 록 페스티벌을 개최하려고 합니다. 이 페스티벌은 여러 날 동안 진행되며, 하루에 한 팀의 밴드가 공연장에서 콘서트를 하게 됩니다. 전체 밴드를 몇 팀 섭외할 지는 아직 결정하지 않았지만, 페스티벌의 간판 스타인 L개의 팀은 이미 섭외가 끝난 상태입니다. 따라서 페스티벌은 최소 L일 이상 진행하게 됩니다. 이번에 사용할 공연장은 하루 빌리는 데 드는 비용이 매일 매일 다릅니다. 때문에 공연 일정을 잘 정해

algospot.com

 

처음에 생각한 풀이 )

 

  첫 팀부터 시작하여 L팀을 선택하여 평균을 구한 후 다음 팀을 확인하여 이미 구한 평균보다 큰 팀이 나오면 다음 루프를 돌리면 된다고 생각했다.

 

반례 )

 

5 3

1 4 3 4 1

 

  생각한대로 구현을 하면  (1+4+3) / 3 < 4 이기 때문에 최솟값으로 8/3을 저장한 후 다음 루프를 돌지만

답인 탐색하지 않게 되는 (1+4+3+4+1) / 5이다.

 

#include <cstdio>	// scanf(), printf()
#include <algorithm>	// min()
using namespace std;
 
int main(void)
{
    int c, n, l;
    int i, j;
    double ans;
 
    scanf("%d", &c);
    while(c--){
        // a[]는 입력으로 받는 각 팀의 비용, b[]는 최솟값을 확인하기 위한 팀 비용의 합
        int teamNum, a[1000], b[1000];
	ans = 1e9;
 
        scanf("%d%d", &n, &l);
        for(int i = 0; i < n; i++)
            scanf("%d", a+i);

        for(i = 0; i <= n-l; i++){
            teamNum = l;
	        b[i] = 0;
            // 최소 팀의 합
            for(j = i; j < i+l; j++)
                b[i] += a[j];
            for(; j < n; j++){
                // 평균 이하의 팀만 추가
                // 나누기 연산 시 오차 발생 때문에 곱셈 연산 사용
                if((double)a[j]*teamNum <= (double)b[i]){
                    b[i] += a[j];
                    teamNum++;
                }
                else
                    break;
            }
            ans = min(ans, (double)b[i]/teamNum);
        }
        printf("%.11f\n", ans);
    }
    return 0;
}

 

 

풀이 )

 

  위에 반례를 통해 모두 탐색해야 된다는 것을 알게 되었으므로 완전탐색을 통해 구했다.

  

#include <cstdio>
#include <algorithm>
using namespace std;

int main(void)
{
    int c, n, l;
    int i, j, k, sum, check;
    int teamNum, a[1000];
    double ans;

    scanf("%d", &c);
    while(c--){
        ans = 1e9;
        scanf("%d%d", &n, &l);
        for(i = 0; i < n; ++i){
            scanf("%d", a+i);
        }
        for(i = 0; i <= n-l; ++i){
            for(j = l; j <= n-i; ++j){
                sum = 0;
                for(k = 0; k < j; ++k){
                    sum += a[i+k];
                }
                ans = min(ans, (double)sum / j);
            }
        }
        printf("%.11f\n", ans);
    }
    return 0;
}

 

주의점 )

 

- 자료형 (float -> double)

- 출력 자리 수 (7자리 이상)

반응형

'문제풀이 > 알고스팟' 카테고리의 다른 글

[C++] 알고스팟 - CLOCKSYNC  (0) 2020.12.28
[C++] 알고스팟 - BOARDCOVER  (0) 2020.12.28
[C++] 알고스팟 - PICNIC  (0) 2020.11.01

+ Recent posts