4949번: 균형잡힌 세상 (acmicpc.net)

 

4949번: 균형잡힌 세상

하나 또는 여러줄에 걸쳐서 문자열이 주어진다. 각 문자열은 영문 알파벳, 공백, 소괄호("( )") 대괄호("[ ]")등으로 이루어져 있으며, 길이는 100글자보다 작거나 같다. 입력의 종료조건으로 맨 마

www.acmicpc.net

 

 

#include <bits/stdc++.h>
using namespace std;
//균형잡힌 세상
int main() {
    string str;

    getline(cin, str);
    while (str != ".") {
        stack<char> bracket;
        int len = str.size();
        for (int i=0; i<len; i++) {
            if (str[i] == '(' || str[i] == '[') {
                bracket.push(str[i]);
            }
            else if (str[i] == ')' && !bracket.empty() && bracket.top() == '(') {
                bracket.pop();
            }
            else if (str[i] == ']' && !bracket.empty() && bracket.top() == '[') {
                bracket.pop();
            }
            else if (str[i] == ')' || str[i] == ']') {
                bracket.push('a');
                break;
            }
        }
        if (bracket.empty()) {
            printf("yes\n");
        }
        else {
            printf("no\n");
        }
        getline(cin, str);
    }
}

 

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 2×n 타일링 2  (0) 2022.03.14
백준 꿀따기 21758번 (11점 )  (0) 2022.03.11
백준 소수 구하기 1929  (0) 2022.03.07
백준 토마토  (0) 2022.03.07
스택 Stack  (0) 2022.02.04

https://www.acmicpc.net/problem/1934 

 

1934번: 최소공배수

두 자연수 A와 B에 대해서, A의 배수이면서 B의 배수인 자연수를 A와 B의 공배수라고 한다. 이런 공배수 중에서 가장 작은 수를 최소공배수라고 한다. 예를 들어, 6과 15의 공배수는 30, 60, 90등이 있

www.acmicpc.net

 

 

#include <bits/stdc++.h>
using namespace std;
//최소공배수
int gcd(int a, int b) {
	while (b != 0) {
		int last = a % b;
		a = b;
		b = last;
	}
	return a;
}

int main() {
	int t, a, b;
	cin >> t;
	while (t--) {
		cin >> a >> b;
		int g = gcd(a, b);
		printf("%d\n", (a*b)/g);
	}
}

 

 

JW

 

 

#include <bits/stdc++.h>
using namespace std;
//토마토

int main() {
	queue<pair<int, int>> q;
	int n, m;
	int arr[1002][1002] = {0,}, visited[1002][1002] = {0,};
	cin >> n >> m;
	for (int i=1; i<=m; i++) {
		for (int j=1; j<=n; j++) {
			cin >> arr[i][j];
		}
	}

	for (int i=1; i<=m; i++) {
		for (int j=1; j<=n; j++) {
			if (arr[i][j] == 1) {
				q.push({i, j});
				visited[i][j] = 1;
			}
			else if (arr[i][j] == -1) {
				visited[i][j] = 1;
			}
		}
	}
	while (!q.empty()) {
		int x = q.front().first;
		int y = q.front().second;
		q.pop();
		if (x-1 != 0 && arr[x-1][y] == 0 && visited[x-1][y] == 0) {
			q.push({x-1, y});
			arr[x-1][y] = arr[x][y] + 1;
			visited[x-1][y] = 1;
		}
		if (x+1 != m+1 && arr[x+1][y] == 0 && visited[x+1][y] == 0) {
			q.push({x+1, y});
			arr[x+1][y] = arr[x][y] + 1;
			visited[x+1][y] = 1;
		}
		if (y-1 != 0 && arr[x][y-1] == 0 && visited[x][y-1] == 0) {
			q.push({x, y-1});
			arr[x][y-1] = arr[x][y] + 1;
			visited[x][y-1] = 1;
		}
		if (y+1 != n+1 && arr[x][y+1] == 0 && visited[x][y+1] == 0) {
			q.push({x, y+1});
			arr[x][y+1] = arr[x][y] + 1;
			visited[x][y+1] = 1;
		}
	}
	for (int i=1; i<=m; i++) {
		for (int j=1; j<=n; j++) {
			if (visited[i][j] == 0) {
				printf("-1");
				return 0;
			}
		}
	}
	int maxi = 0;
	for (int i=1; i<=m; i++) {
		for (int j=1; j<=n; j++) {
			if (arr[i][j] > maxi) {
				maxi = arr[i][j];
			}
		}
	}
	printf("%d", maxi-1);
}

 

 

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 균형잡힌 세상  (0) 2022.03.07
백준 소수 구하기 1929  (0) 2022.03.07
스택 Stack  (0) 2022.02.04
단어 뒤집기 2  (0) 2021.12.31
백준 : 가운데를 말해요 1655번  (0) 2020.05.10

https://www.acmicpc.net/problem/1717

 

1717번: 집합의 표현

첫째 줄에 n(1≤n≤1,000,000), m(1≤m≤100,000)이 주어진다. m은 입력으로 주어지는 연산의 개수이다. 다음 m개의 줄에는 각각의 연산이 주어진다. 합집합은 0 a b의 형태로 입력이 주어진다. 이는 a가 포함되어 있는 집합과, b가 포함되어 있는 집합을 합친다는 의미이다. 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산은 1 a b의 형태로 입력이 주어진다. 이는 a와 b가 같은 집합에 포함되어 있는지를 확인하는 연산이다. a

www.acmicpc.net

 

 

 

#include<stdio.h>
#include<bits/stdc++.h>

using namespace std;
//집합의 표현 1717번

vector<int> v;  //(본인정보, 부모정보)

int my_find(int me)
{
    if(me == v[me])
    {
        return me;
    }
    return v[me] = my_find(v[me]);
}

void my_union(int a, int b)
{
    int A = my_find(a);
    int B = my_find(b);

    if(A == B)
    {
        return;
    }

    v[A] = B;
}

int main(void)
{
    int n,m;
    int q, from, to;
    scanf("%d %d", &n, &m);
    v.push_back(0);

    for(int i=1; i<=n; i++)
    {
        v.push_back(i);
    }

    for(int i=0; i<m; i++)
    {
        scanf("%d %d %d", &q, &from, &to);
        if(q == 0)
        {
            my_union(from, to);
        }

        else if(q==1)
        {
            if(my_find(from) == my_find(to))
            {
                printf("YES \n");
            }
            else
            {
                printf("NO \n");
            }
        }


    }

	return 0;
}

https://www.acmicpc.net/problem/16917

 

16917번: 양념 반 후라이드 반

현진 치킨에서 판매하는 치킨은 양념 치킨, 후라이드 치킨, 반반 치킨으로 총 세 종류이다. 반반 치킨은 절반은 양념 치킨, 절반은 후라이드 치킨으로 이루어져있다. 양념 치킨 한 마리의 가격은 A원, 후라이드 치킨 한 마리의 가격은 B원, 반반 치킨 한 마리의 가격은 C원이다. 상도는 오늘 파티를 위해 양념 치킨 최소 X마리, 후라이드 치킨 최소 Y마리를 구매하려고 한다. 반반 치킨을 두 마리 구입해 양념 치킨 하나와 후라이드 치킨 하나를 만드는 방법도 가

www.acmicpc.net

 

 

#include<stdio.h>
#include<vector>
#include<cmath>
#include<cstring>
using namespace std;
//양념 반 후라이드 반
int main(void)
{
    int a,b,c,x,y;//양후반
    int res=0;

    scanf("%d %d %d %d %d", &a, &b, &c, &x, &y);

    if(2*c<(a+b))
    {
        while((x>0) && (y>0))
        {
            x--;
            y--;
            res+=2*c;
        }
        if(x>0)
        {
            if(2*c<a)
            {
                res+=(x*2*c);
            }
            else
            {
                res+=a*x;
            }
        }
        else if(y>0)
        {
            if(2*c<b)
            {
                res+=(y*2*c);
            }
            else
            {
                res+=b*y;
            }
        }
    }
    else//a+b<2c    a or b >2c
    {
        res+= a*x + b*y;
    }

    printf("%d", res);

	return 0;
}

 

https://www.acmicpc.net/problem/15971

 

15971번: 두 로봇

2018년 강원도에서 새로운 동굴이 발견되었다. 이 동굴에는 총 N개의 넓은 방이 존재하며 좁은 통로로 서로 연결되어 있는 것으로 밝혀졌다. N개의 방은 1번부터 N번까지의 번호를 붙여 1번 방, 2번 방, …, N번 방으로 부른다. 통로는 정확히 N-1개가 발견되었는데, 각각 서로 다른 두 방 사이를 연결시켜 주며 중간에 다른 통로와 이어지는 경우는 없다고 한다. 또한 이 통로들을 이용하여 임의의 두 방 사이를 이동하는 것이 가능하며, 임의의 두 방 사

www.acmicpc.net

 

 

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
/*
5 1 5
1 2 1
2 3 2
3 4 3
4 5 4
*/
int vi[100010],max1,tot;
vector <pair<int,int>> v[100010];

void dfs(int s, int e, int lmax, int l)
{
    if(s==e) {
        max1=lmax;
        tot=l;
    }
    else{
        vi[s]++;
        for(int i=0;i<v[s].size();i++)
        {
            if(vi[v[s][i].first]==0)
            {
                int last=lmax>v[s][i].second?lmax:v[s][i].second;
                dfs(v[s][i].first,e,last,l+v[s][i].second);
            }
        }
    }

}
int main()
{
    int r,r1,r2,i,s,e,d;

    scanf("%d %d %d",&r,&r1,&r2);
    for(i=1;i<r;i++)
    {
        scanf("%d %d %d",&s,&e,&d);
        v[s].push_back(make_pair(e,d));
        v[e].push_back(make_pair(s,d));
    }
    dfs(r1,r2,0,0);
    printf("%d",tot-max1);
    return 0;
}

https://www.acmicpc.net/problem/17618

 

17618번: 신기한 수

평소에 수에 대한 관심이 많은 아이인 민철이는 오늘도 노트에 연필로 수를 더하거나 빼거나 곱하거나 나눠보면서 시간을 보내고 있다. 그러다가 18이라는 수는 신기한 성질을 가진다는 것을 알아냈다. 18을 이루는 각 자릿수인 1과 8을 합한 9는 18의 약수가 된다. 민철이는 18과 같이 모든 자릿수의 합으로 나누어지는 수를 여러 개 더 찾아냈는데, 12, 21도 그런 신기한 수였다. 민철이는 이렇게 모든 자릿수의 합으로 나누어지는 수를 “신기한 수”라고 부

www.acmicpc.net

 

 

 

#include<bits/stdc++.h>
using namespace std;

int sum; 
void Div_sum(int num)
{
    if(num == 0)
    {
        return;
    }

    sum+=(num%10);
    Div_sum(num/10);
}

int main(void)
{
    int n;
    int cnt=0;
    scanf("%d", &n);

    for(int i=1; i<=n; i++)
    {
        Div_sum(i);
        if((i%sum) == 0)
        {
            cnt++;
        }
        sum = 0;
    }

    printf("%d", cnt);

    return 0;
}

 

 

#include <bits/stdc++.h>
using namespace std;

int main() {
  int a;
  cin >> a;
  int cnt = 0;
  for(int i=1; i <=a; i ++)
  {
    int sum = 0;
    int temp = i;
    while(temp){
      sum = sum + temp%10;
      temp = temp / 10;
    }
    //cout << "== " << sum << "\n";
    if( i % sum == 0) cnt ++;
  }

  cout << cnt;
  
}

https://www.acmicpc.net/problem/17619

 

17619번: 개구리 점프

첫 번째 줄에 통나무 개수 N과 질문의 개수 Q가 주어진다. 다음 N개의 줄에 각 통나무에 x1, x2, y의 세 정수 좌표가 주어진다. 주어진 통나무는 두 점 (x1, y)와 (x2, y)를 잇는 형태이다. (x1 < x2) 모든 좌표는 0이상 109이하이다. 통나무들은 주어진 순서대로 1번부터 번호가 붙어 있다. 서로 다른 두 통나무는 (끝점에서도) 만나지 않는다. 다음 Q개의 줄에 서로 다른 두 통나무의 번호가 주어진다. (1 ≤ N ≤ 100,00

www.acmicpc.net

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//2019 정올 2차 2번 문제 (중등)
struct s{
    int a,b,pos;
};
bool compare(struct s x,struct s y)
{
    //return x.a<y.a;

    if(x.a<y.a)
        return true;
    return false;
}
int main()
{
    int m,n,i,j,y,r1[1000000]={0,},r2[1000000]={0,},max1,k=0,t=0,z=0,flag=0;
    int g2[1000000];
    struct s log[1000000];
    scanf("%d %d",&m,&n);
    for(i=0;i<m;i++){
        scanf("%d %d %d",&log[i].a,&log[i].b,&y);
        log[i].pos=i+1;
        g2[log[i].pos] = log[i].pos;
    }

    for(i=0;i<n;i++)
        scanf("%d %d",&r1[i],&r2[i]);
    sort(log,log+m,compare);
    while(1)
    {
        max1=log[t].b;
        
        int group = g2[log[t].pos];
        for(i=t;i<m-1;i++)
        {
            if(log[i+1].a<=max1)
            {
                
                g2[log[i+1].pos] = group;
                if(log[i+1].b>max1)
                    max1=log[i+1].b;
            }
            else
                break;
        }
        t=i+1;
        k++;
        z=0;
        if(t>=m)
            break;
    }


    for(t=0;t<n;t++)
    {
        if(g2[r1[t]] == g2[r2[t]]) puts("1");
        else puts("0");
    }
    return 0;
}

https://www.acmicpc.net/problem/1182

 

1182번: 부분수열의 합

첫째 줄에 정수의 개수를 나타내는 N과 정수 S가 주어진다. (1 ≤ N ≤ 20, |S| ≤ 1,000,000) 둘째 줄에 N개의 정수가 빈 칸을 사이에 두고 주어진다. 주어지는 정수의 절댓값은 100,000을 넘지 않는다.

www.acmicpc.net

 

 

#include 
#include <bits/stdc++.h>
using namespace std;
/*
부분수열의 합
*/
int a[10000]={0,};
int main()
{
    int n,s,i,k,sum=0,cnt=0;
    scanf("%d %d",&n,&s);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<(1<<n);i++){
        sum=0;
        for(k=0;k<n;k++)
        {
            if(i&(1<<k))
            {
                sum+=a[k+1];
            }
        }
        if(sum==s)
            cnt++;
    }
    printf("%d",cnt);
    return 0;
}

https://www.acmicpc.net/problem/1463

 

1463번: 1로 만들기

첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.

www.acmicpc.net

 

 

#include <bits/stdc++.h>
using namespace std;

int main()
{
    long long int n,a[1000001]={0,},i;
    scanf("%lld",&n);

    for(i=2;i<=n;i++)
    {
        a[i]=a[i-1]+1;
        if(i%2==0 && a[i] > a[i/2] + 1)
            a[i] = a[i/2] + 1;
        if(i%3==0 && a[i] > a[i/3] + 1)
            a[i] = a[i/3] + 1;
    }

    /*
    for(i=1; i<=n; i++)
        printf("%lld : %lld  \n",i, a[i]);
        */
    printf("%d", a[n]);
    return 0;
}

https://www.acmicpc.net/problem/10819

 

10819번: 차이를 최대로

첫째 줄에 N (3 ≤ N ≤ 8)이 주어진다. 둘째 줄에는 배열 A에 들어있는 정수가 주어진다. 배열에 들어있는 정수는 -100보다 크거나 같고, 100보다 작거나 같다.

www.acmicpc.net

 

 

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,a[1000000]={0,},max1=0,i,tmp=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    do
    {
        for(i=1;i<=n-1;i++)
        {
            tmp+=abs(a[i]-a[i+1]);
            if(max1<tmp)
            {
                max1=tmp;
            }
        }
        tmp=0;
    }while(next_permutation(a+1,a+n+1));
    printf("%d",max1);
    return 0;
}

https://www.acmicpc.net/problem/14002

 

14002번: 가장 긴 증가하는 부분 수열 4

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

www.acmicpc.net

아래 코드를 먼저 참고바랍니다.

https://coding-gongboo.tistory.com/38?category=829643

 

백준-가장 긴 증가하는 부분 수열 : 11053번 ( LIS)

https://www.acmicpc.net/problem/11053 11053번: 가장 긴 증가하는 부분 수열 수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50..

coding-gongboo.tistory.com

11053번 문제는 수열의 길이만 구하면 되지만, 14002문제는 수열을 표현해 주어야 한다.

 

#include <iostream>
#include <stdio.h>
using namespace std;

int main()
{
    int n,i,a[1000]={0,},l[1000]={0,},j,ma=-1,k[1000]={0,},m;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(i=1;i<=n;i++)
    {
        l[i]=1;
        k[i]=i;
        for(j=1;j<i;j++)
        {
            if(a[j]<a[i])
            {
                //l[i]=l[i]>l[j]+1 ? l[i] : l[j]+1;
                if(l[i] < l[j]+1)
                {
                    l[i] = l[j]+1;
                    k[i]=j;
                }
            }
        }
       // ma=ma>l[i]?ma:l[i];
        if(ma<l[i]){
            ma=l[i];
            m=i;
        }
    }
    printf("%d\n",ma);
    l[1] = a[m];
    for(i=2;i<=ma;i++)
    {
        l[i]=a[k[m]];
        m = k[m];
    }
    for(i=ma;i>0;i--)
        printf("%d ",l[i]);
    return 0;
}

https://www.acmicpc.net/problem/11053

 

11053번: 가장 긴 증가하는 부분 수열

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

www.acmicpc.net

이문제는 LIS(Longest Increasing Subsequence) 라는 유명한 문제입니다.

 

아래 코드는 다이내믹 방식으로 소스코드를 작성했습니다.

 

참고하시구요. 질문이나 수정할 부분있으면 알려주세요.^^

 

#include <iostream>
#include <stdio.h>
using namespace std;

int main()
{
    int n,i,a[100000]={0,},l[100000]={0,},j,ma=-1;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(i=1;i<=n;i++)
    {
        l[i]=1;
        for(j=1;j<i;j++)
        {
            if(a[j]<a[i])
                l[i]=l[i]>l[j]+1 ? l[i] : l[j]+1;
        }
        ma=ma>l[i]?ma:l[i];
    }
    printf("%d",ma);
    return 0;
}

https://www.acmicpc.net/problem/1697

 

1697번: 숨바꼭질

문제 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다. 수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지

www.acmicpc.net

BFS를 사용해서 쉽게풀수 있는 문제다.

BFS는 아래그림과 같이 그래프 순회방법중의 하나이다.

특히, BFS는 간선의 가중치가 모두 동일한 경우, 최단거리와 같은 최소비용 문제를 해결하기에 적합합니다.

 

아래 그래는 Graph의 표현 방법과 순회에 대해서 대략적으로 요약한 것이니 참고하시기 바랍니다.

인접리스트의 경우 실제 리스트를 사용하기 보다는 보통 vector를 사용해서 해결하는 경우 많으니 참고하세요.

 

 

아래 BFS의 슈도코드라고 할까요? 대략적인 알고리즘을 확인 하실수 있겠습니다.

 

자~!! 이제 본 숨바꼭질 문제의 풀이 방법입니다. 아래 그림을 통해 찬찬히 고민해보시기 바랍니다.

수빈이의 위치 X에서 1초후에 이동할 수 있는 곳은 X-1, X+1, X*2 입니다. 어떤 이동방법을 선택하더라도 1초가 걸리니까, 이것은 모든 간선의 가중치가 1초라고 보면 되겠네요.^^

 

그리고X-1을 할때는 X-1이 0보다 작으면 중단하면 되겠죠.

X+1, X*2의 경우는 다음 위치가 200,000보다 작거나 같은때만 처리해주면 되겠네요.^^

 

 

많은 도움되셨길바라며, 아래 소스코드 참고하세요.^^

 

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,k,c[200005]={0,},v[200005]={0,},t;
    queue <int> q;
    scanf("%d %d",&n,&k);
    v[n]=1;
    c[n]=0;
    q.push(n);
    while(!q.empty())
    {
        t=q.front();
        q.pop();
        if(t-1 >= 0 && v[t-1]==0){
            q.push(t-1);
            c[t-1]=c[t]+1;
            v[t-1] = 1;
        }
        if(t+1 < 200000 && v[t+1]==0){
            q.push(t+1);
            c[t+1]=c[t]+1;
            v[t+1] = 1;
        }
         if(t*2 < 200000 && v[t*2]==0){
            q.push(t*2);
            c[t*2]=c[t]+1;
             v[t*2]=1;
        }
        //v[t-1]=v[t+1]=v[t*2]=1;
    }
    printf("%d",c[k]);
    return 0;
}

 

https://www.acmicpc.net/problem/11727

 

11727번: 2×n 타일링 2

첫째 줄에 2×n 크기의 직사각형을 채우는 방법의 수를 10,007로 나눈 나머지를 출력한다.

www.acmicpc.net

전형적인 다이내믹 (동적계획법)문제다.

점화식은 아래 스케치를 참고하세요.^^

 

점화식 : K(n) = K(n-1) + 2*K(n-2)

 

 

<Top-Down - 재귀함수 사용 방법>

#include<bits/stdc++.h>
using namespace std;

int d[1001];

int tile(int n)
{
    if(n < 2) return 1;
    if(d[n] > 0) return d[n];
    
    d[n] = (tile(n-1) + tile(n-2) + tile(n-2))%10007;
    return d[n];
}
int main() {

    int n;
    scanf("%d",&n);

    printf("%d\n",tile(n));
    return 0;
}

 

<Bottom-Up>

#include<stdio.h>
int k[1004];
int main()
{
	int n,i,j;
	scanf("%d",&n);
	for(i=1; i<=1004; i++)k[i]=0;
	k[1]=1;
	k[2]=3;
	for(i=3; i<=n; i++){
        k[i]=k[i-1]+k[i-2]*2;
	}
	printf("%d",k[n]%10007);
	return 0;
}

 

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준-부등호 : 2529번  (0) 2020.01.15
백준 - 숨바꼭질 : 1697번  (0) 2020.01.11
백준 - 최소,최대 : 10818번  (0) 2020.01.02
백준 - 동전 0 : 11047번  (0) 2020.01.02
백준-N-Queen : 3344번  (0) 2019.12.26

https://www.acmicpc.net/problem/3344

 

3344번: N-Queen

문제 8*8 체스보드에 8개의 퀸을 서로 공격하지 못하게 놓는 문제는 잘 알려져 있는 문제이다. 퀸은 같은 행, 열, 또는 대각선 위에 있는 말을 공격할 수 있다. 이 문제의 한가지 정답은 아래 그림과 같다. 이 문제의 조금 더 일반화된 문제는 Franz Nauck이 1850년에 제기했다. N*N 보드에 N개의 퀸을 서로 다른 두 퀸이 공격하지 못하게 놓는 경우의 수는 몇 가지가 있을까? 이 문제는 N>3인 경우에 경우의 수가 적어도 1개 라는 것이 증명

www.acmicpc.net

N-Queen문제 생각보다 어렵죠? 아마도 N-Queen문제에서 막혀서 찾아오셨다면, 아마도 백트랙킹 / 재귀함수에 대해서 아주 조금 이해가 힘드셔서 오셨을것 같네요.^^ 아래 코드보시면서 도움 되시기 바랍니다.

 

각 행을 한개씩 내려가면서 Queen을 놓을 곳을 찾아가면 될것 같다.

첫번째 행의 어느 열에 Queen을 위치시키면, 그 열과 대각선 방향을 더이상 Queen을 놓을수 없음을 표시해야 한다.

 

bool check_right_up[100]; //이미 대각선 오른쪽 위로 queen이 있는지 확인
위 코드는 아래 그림을 보고 이해할 수 있길 바랍니다. 대각선의 각 cell의 행값 + 열값은 unique하다는 걸 이용해서,

그 unique한 값을 배열의 index로 사용해서, 그 대각선에 이미 Queen이 위치해 있음을 판단하면 됩니다.

 

bool check_right_down[100]; //이미 대각선 오른쪽 아래로 queen이 있는지 확인

아래 그림은 행-열을 한 값을 표시하고 있다. 음수가 발생하니, 모든 값들에 N을 더하면,

1,2,3,4,5,6,7 로 unique한 값을 만들수 있고, 이것을 배열의 index로 이용하면 됩니다.

 

#include <bits/stdc++.h>
using namespace std;
bool a[15][15];
int n;
bool check_col[15]; //이미 그 열에 queen이 있는지 확인
bool check_right_up[100]; //이미 대각선 오른쪽 위로 queen이 있는지 확인
bool check_right_down[100]; //이미 대각선 오른쪽 아래로 queen이 있는지 확인

void check_onoff(int row, int col, bool onoff)
{
    check_right_up[row + col] = onoff;
    check_right_down[row - col + n] = onoff;
    check_col[col] = onoff;
    a[row][col] = onoff;
}
bool check(int row, int col) {
    // 같은 열 확인
    if (check_col[col]) {
        return false;
    }
    // 오른쪽 위방향 대각선 확인 (왼쪽 아래도^^)
    if (check_right_up[row + col]) {
        return false;
    }
    // 오른쪽 아래 방향 대각선 확인 (왼쪽 위도^^)
    if (check_right_down[row - col + n]) {
        return false;
    }
    return true;
}

int N_Queen(int row) {
    if (row == n) {
        return 1;
    }
    int cnt = 0;
    for (int col = 0; col < n; col++) {
        if (check(row, col)) { //이 row, col위치에 놓을수 있을지 확인
            check_onoff(row, col, true);  //놓을 수 있으니까, 그 위치 관련해서 놓았다는 표시를 함
            cnt += N_Queen(row + 1);  //다음 행에 queen을 놓으로 감.
            check_onoff(row, col, false); //row, col 기준으로 확인해보 후 임으로, 다시 해제함.
        }
    }
    return cnt;
}
int main() {
    cin >> n;
    cout << N_Queen(0) << '\n';
    return 0;
}

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - 최소,최대 : 10818번  (0) 2020.01.02
백준 - 동전 0 : 11047번  (0) 2020.01.02
백준 - 타일링 : 1793번  (0) 2019.12.23
백준 - DFS와 BFS : 1260번  (0) 2019.12.22
백준 - N과 M (4) :15652 번  (0) 2019.12.19

 

https://www.acmicpc.net/problem/1260

 

1260번: DFS와 BFS

첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사이에 여러 개의 간선이 있을 수 있다. 입력으로 주어지는 간선은 양방향이다.

www.acmicpc.net

1. 단계 : 시작 정점을 방문했다고 표시하고, Queue에 push

void bfs(int start){
    checked[start]=1;
    queue<int> q;
    q.push(start);
    while(!q.emplace()){
        
    }
}

2. 단계 
시작 정점을 방문했다고 표시하고, Queue에 push
Queue가 빌때까지 반복하면서, queue의 front값을 받고, pop함

void bfs(int start){
    checked[start]=1;
    queue<int> q;
    q.push(start);
    while(!q.empty()){
        int current = q.front();
        q.pop();
        printf("%d ", current);
    }
}

3. 단계
시작 정점을 방문했다고 표시하고, Queue에 push
Queue가 빌때까지 반복하면서, queue의 front값을 받고, pop함

queue의 front 정점(current)을 대상으로 연결된 정점(next)들을 찾음
next중에 방문하지 않은 정점이면, 방문 표시하고 queue에 push
이것을 queue가 빌때까지 반복

void bfs(int start){
    checked[start]=1;
    queue<int> q;
    q.push(start);
    while(!q.empty()){
        int current = q.front();
        q.pop();
        printf("%d ", current);
        for(int i=0; i<vxy[current].size(); i++){
            int next=vxy[current][i];
            if(checked[next] == 0){
                q.push(next);
                checked[next]=1;
            }
        }
    }
}

 

 

전체 소스코드

#include <bits/stdc++.h>
using namespace std;
int checked[10000];
vector<int>vxy[10000];

void dfs(int start)
{
    checked[start]=1;
    printf("%d ",start);
    for(int i=0; i<vxy[start].size(); i++){
        int next=vxy[start][i];
        if(checked[next] == 0){
            dfs(next);
        }
    }
}

void bfs(int start){
    checked[start]=1;
    queue<int> q;
    q.push(start);
    while(!q.empty()){
        int current = q.front();
        q.pop();
        printf("%d ", current);
        for(int i=0; i<vxy[current].size(); i++){
            int next=vxy[current][i];
            if(checked[next] == 0){
                q.push(next);
                checked[next]=1;
            }
        }
    }
}

int main() {
    int a,b,c,n,m,i;
    scanf("%d %d %d",&n,&m,&c);
    for(i=1; i<=m; i++){
        scanf("%d %d",&a,&b);
        vxy[a].push_back(b);
        vxy[b].push_back(a);
    }

    for(i=1; i<=n; i++){
        sort(vxy[i].begin(),vxy[i].end());
    }

    dfs(c);
    for(i=0; i<=n; i++)checked[i]=0;
    printf("\n");
    bfs(c);

    return 0;
}

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준-N-Queen : 3344번  (0) 2019.12.26
백준 - 타일링 : 1793번  (0) 2019.12.23
백준 - N과 M (4) :15652 번  (0) 2019.12.19
백준 - N과 M (3) : 15651번  (0) 2019.12.19
백준 - A/B : 1008번  (0) 2019.12.19

https://www.acmicpc.net/problem/15652

 

15652번: N과 M (4)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다.

www.acmicpc.net

이번문제는 N과 M (2)와 유사하다. 단, 중복 가능하다. 

아래 문제 조건과 같이 앞의 수가 다음수보다 작거나 같다은 조건을 만족하면 된다.

길이가 K인 수열 A가 A1 ≤ A2 ≤ ... ≤ AK-1 ≤ AK를 만족하면, 비내림차순이라고 한다.

 

따라서 N과 M (2)에서 재귀함수의 첫번째 인자만, i+1이 아니랑 i를 주면 된다.

즉, i값을 포함해서 다음 수를 정해나가는 형태이다. 왜냐? 중복을 허용하기 때문이다.

 

#include <bits/stdc++.h>
using namespace std;
vector <int> nm;
void NM4(int, int, int);

int main() {
    int n, m;
    cin >> n >> m;
    NM4(1, n, m);
    return 0;
}
void NM4(int s, int n, int m) {
    if (nm.size() == m) {
        for (int i = 0; i < m; i++) {
            cout << nm[i] << " ";
        }
        cout << '\n';
        return;
    }
    for (int i = s; i <= n; i++) {
        nm.push_back(i);
        NM4(i, n, m); //현재 nm vector에 넣은 수 이후 수를 확인 한다. (오름차순)
        nm.pop_back();
    }
}

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - 타일링 : 1793번  (0) 2019.12.23
백준 - DFS와 BFS : 1260번  (0) 2019.12.22
백준 - N과 M (3) : 15651번  (0) 2019.12.19
백준 - A/B : 1008번  (0) 2019.12.19
백준 - 개 : 10172번  (0) 2019.12.19

https://www.acmicpc.net/problem/15651

 

15651번: N과 M (3)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다.

www.acmicpc.net

자연수 N과 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오. (중복가능)

 

N = 4, M = 2인 경우 아래와 같이 16(4*4) 개의 경우가 발생한다.

1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4
3 1
3 2
3 3
3 4
4 1
4 2
4 3
4 4

 

내 생각에는 N과 M(1)보다 풀이에 접근하기 더 쉬운 문제라고 생각한다. 내기준으로는 "N과 M(0)" 이 맞을듯.^^

 

#include <bits/stdc++.h>
using namespace std;
vector <int> res;
void NM3(int n, int m) {
    if (res.size() == m) {
        for (int i = 0; i < m; i++) {
            cout << res[i] << " ";
        }
        cout << '\n';
        return;
    }
    for (int i = 1; i <= n; i++) {
        res.push_back(i);
        NM3(n, m);
        res.pop_back();
    }
}
int main() {
    int n, m;
    cin >> n >> m;
    NM3(n, m);
    return 0;
}

 

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - DFS와 BFS : 1260번  (0) 2019.12.22
백준 - N과 M (4) :15652 번  (0) 2019.12.19
백준 - A/B : 1008번  (0) 2019.12.19
백준 - 개 : 10172번  (0) 2019.12.19
백준 - 단지번호붙이기 : 2667번  (0) 2019.12.19

https://www.acmicpc.net/problem/1008

 

1008번: A/B

두 정수 A와 B를 입력받은 다음, A/B를 출력하는 프로그램을 작성하시오.

www.acmicpc.net

 

float 형의 경우 대략 10^-7 정도의 오차를 갖으며,

double 형의 경우 대략 10^-15 정도의 오차를 갖습니다. 그래서 10-9 이하의 오차를 가지려면 doule형을 사용해야 한다.

 

https://kin.naver.com/qna/detail.nhn?d1id=1&dirId=1040101&docId=329881326&qb=ZG91YmxlIGZsb2F0IOyYpOywqA==&enc=utf8§ion=kin&rank=1&search_sort=0&spq=0

 

c언어 float /double 질문

#include int main(void){ int num1; float num = 0.0f; // 실수를 사용 할 때 왠만하면 float 는 사용x 실...

kin.naver.com

 

#include <bits/stdc++.h>
using namespace std;

int main() {
	double A, B;
	scanf("%lf %lf", &A, &B);
	printf("%.9lf\n", A / B);
	return 0;
}

https://www.acmicpc.net/problem/10172

 

10172번: 개

문제 아래 예제와 같이 개를 출력하시오. 입력 출력 예제 입력 1 복사 예제 출력 1 복사 |\_/| |q p| /} ( 0 )"""\ |"^"` | ||_/=\\__|...

www.acmicpc.net

특수문자 출력 연습하기~!!!

#include <bits/stdc++.h>
using namespace std;

int main() {

	printf("|\\_/|\n");
	printf("|q p|   /}\n");
	printf("( 0 )\"\"\"\\\n");
	printf("|\"\^\"`    |\n");
	printf("||_/=\\\\__|\n");

	return 0;

}

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - N과 M (3) : 15651번  (0) 2019.12.19
백준 - A/B : 1008번  (0) 2019.12.19
백준 - 단지번호붙이기 : 2667번  (0) 2019.12.19
백준 - 연결 요소의 개수 : 11724번  (0) 2019.12.18
백준 - 윤년 : 2753번  (0) 2019.12.18

https://www.acmicpc.net/problem/11724

 

11724번: 연결 요소의 개수

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주어진다.

www.acmicpc.net

연결 요소의 개수의 경우, DFS나 BFS를 공부를 공부한 후라면 간단하게 해결 가능하다.

 

모든 정점을 대상으로 방문한 적이 없는 정점이 있으면 그 정점을 기준으로 DFS 또는 BFS순회를 통해 방문했다는 체크를 해둔다. 그 후에도 아직 방문하지 않은 정점이 있다면 또 DFS나 BFS를 통해 순회하면서 방문했다는 체크를 하면 된다.

 

#include <bits/stdc++.h>
using namespace std;

int n, l;
vector <int> a[1005];
int visited[1005] = { 0, };

void dfs_l(int s) {
    int i;
    visited[s]++;
    for (i = 0; i < a[s].size(); i++){
        if (visited[a[s][i]] == 0){
            dfs_l(a[s][i]);
        }
    }

}

int main()
{
    int i, n1, n2, cnt = 0;
    scanf("%d %d", &n, &l);
    //간선 정보를 입력 받아 그래프 만들기
    for (i = 0; i < l; i++){
        scanf("%d %d", &n1, &n2);
        a[n1].push_back(n2);
        a[n2].push_back(n1);
    }
    
    //DFS 순회시에 인접 정점중에 정점번호가 작은 값부터 순회하기 위해 정렬
    //이번 문제에서는 굳이 없어도 됨.
    for (int i = 0; i < n; i++) {
        sort(a[i].begin(), a[i].end());
    }
    //방문하지 않은 정점을 발견하면 DFS순회함.
    //DFS가 호출되는 횟수가 연결요소의 개수가 됨.
    for (int i = 1; i <= n; i++){
        if (visited[i] == 0){
            dfs_l(i);
            cnt++;
        }
    }
    printf("%d", cnt);
    return 0;
}

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - 개 : 10172번  (0) 2019.12.19
백준 - 단지번호붙이기 : 2667번  (0) 2019.12.19
백준 - 윤년 : 2753번  (0) 2019.12.18
백준 - 고양이 : 10171번  (0) 2019.12.18
백준 - N과 M (2) : 15650번  (0) 2019.12.18

https://www.acmicpc.net/problem/15650

 

15650번: N과 M (2)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다.

www.acmicpc.net

 

N과 M(1)문제 풀이 참고바람. (https://coding-gongboo.tistory.com/9?category=829643)

 

N과 M(1) 과의 차이점은 "고른 수열은 오름차순이어야 한다"는 점이다.

이를 위해서 현재 선택된 수 보다 1개 높은 위치의 수를 부터 수열을 만들어 나가야 한다.

이를 위해서 NM2(재귀함수)에 start해야 할 위치를 인자로 넘겨주는 부분이 수정되었다.

 

그리고 항상 다음 수를 대상으로 수열을 만들어 나가기 때문에 중복체크를 위한 included배열은 필요없다.

 

#include <bits/stdc++.h>

using namespace std;
//bool included[10]; //중복 체크
vector <int> nm;
void NM2(int, int, int);

int main() {
    int n, m;
    cin >> n >> m;
    NM2(1, n, m);
    return 0;
}

void NM2(int s, int n, int m) {
    if (nm.size() == m) {
        for (int i = 0; i < m; i++) {
            cout << nm[i] << " ";
        }
        cout << '\n';
        return;
    }
   
    for (int i = s; i <= n; i++) {
        //if (!included[i]) {
            //included[i] = true;
            nm.push_back(i);
            NM2(i + 1, n, m); //현재 nm vector에 넣은 수 이후 수를 확인 한다. (오름차순)
            nm.pop_back();
            //included[i] = false;
        //}
    }
}

 

두번째 풀이

각 수들을 포함 하거나 또는 포함 하지않으면서 다음수로 넘어가는 형태

 

#include <bits/stdc++.h>
using namespace std;
vector <int> nm;
void NM2(int level, int n, int m);

int main() {
    int n, m;
    cin >> n >> m;
    NM2(1, n, m);
    return 0;
}

void NM2(int level, int n, int m) {
    if (nm.size() == m) {
        for (int i = 0; i < m; i++) {
            cout << nm[i] << " ";
        }
        cout << '\n';
        return;
    }
    if (level > n) return;
    nm.push_back(level);
    NM2(level + 1, n, m);
    nm.pop_back();
    NM2(level + 1, n, m);
}

 

세번째 풀이

배열을 사용해서 결과값을 저장한 위치에 해당하는 index 인자를 관리해주고,

오름차순을 위해 다음 수를 지정해주는 start를 관리해 주는 형태

 

#include <bits/stdc++.h>
using namespace std;
int res[10];
void go(int index, int start, int n, int m);

int main() {
    int n, m;
    cin >> n >> m;
    go(0, 1, n, m);
    return 0;
}

void go(int index, int start, int n, int m) {
    if (index == m) {
        for (int i = 0; i < m; i++) {
            cout << res[i];
            if (i != m - 1) cout << ' ';
        }
        cout << '\n';
        return;
    }
    for (int i = start; i <= n; i++) {
        res[index] = i;
        go(index + 1, i + 1, n, m);
    }
}

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - 연결 요소의 개수 : 11724번  (0) 2019.12.18
백준 - 윤년 : 2753번  (0) 2019.12.18
백준 - 고양이 : 10171번  (0) 2019.12.18
백준 - N과 M (1) : 15649번  (0) 2019.12.17
백준 문제소 내용을 정리  (0) 2019.12.17

https://www.acmicpc.net/problem/15649

 

15649번: N과 M (1)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다.

www.acmicpc.net

자연수 N과 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.

  • 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열

N=4, M=4가 주어지면, 아래와 같이 12(4*3)개의 경우가 발생한다.

아래 1 4 와 4 1과 같이 순서가 다른 경우는 다른 것으로 판단해야 함.

1 2
1 3
1 4
2 1
2 3
2 4
3 1
3 2
3 4
4 1
4 2
4 3

 

"중복 없이"라는 조건이 있음으로 한번 수열에 포함된 수는 수열을 완성할때까지 다시 포함되면 안됨으로 포함 여부를 판단하기 위해 included라는 배열을 사용한다.

 

n = 4, m = 2를 입력하면, 아래와 같은 순서로 실행된다.

 

"1. go(4,2)" : nm에 1추가 (nm = 1)

"2. go(4,2)" : nm에 2추가 (nm = 1,2)

"3. go(4,2)" : nm.size()가 m임으로 nm의 내용 1,2 출력 후 return

"2. go(4,2)" 로 돌아감. nm에서 2를 pop_bakc하고, for문을 통해 i 증가시킨 후 nm에 3을 추가함.

 

 

 

#include <bits/stdc++.h>

using namespace std;
bool included[10]; //중복 체크
vector <int> nm;
void NM1(int, int);

int main() {
    int n, m;
    cin >> n >> m;
    NM1(n, m);
    return 0;
}

void NM1(int n, int m) {
    if (nm.size() == m) {
        for (int i = 0; i < m; i++) {
            cout << nm[i] << " ";
        }
        cout << '\n';
        return;
    }
    for (int i = 1; i <= n; i++) {
        if (!included[i]) {
            included[i] = true;
            nm.push_back(i);
            NM1(n, m);
            nm.pop_back();
            included[i] = false;
        }
    }
}

 

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - 연결 요소의 개수 : 11724번  (0) 2019.12.18
백준 - 윤년 : 2753번  (0) 2019.12.18
백준 - 고양이 : 10171번  (0) 2019.12.18
백준 - N과 M (2) : 15650번  (0) 2019.12.18
백준 문제소 내용을 정리  (0) 2019.12.17

지난 몇개월 동안 백준 문제풀이 사이트에서 딱 204개의 문제를 풀어봤다. 

2020년도 안에 300문제정도를 더 풀어서 백준사이트 랭킹 1000등안에는 들어가볼 계획이다.

내가 직접푼 소스코드는 물론이고, 학생들과 공부하는 과정에서 얻은 주옥같은 코드들도 공유하려한다.

 

대한민국이 SW강국이 되는 그날을 기대하며.......

 

https://www.acmicpc.net/

 

Baekjoon Online Judge

Baekjoon Online Judge 프로그래밍 문제를 풀고 온라인으로 채점받을 수 있는 곳입니다.

www.acmicpc.net

 

'정보올림피아드-KOI > BOJ' 카테고리의 다른 글

백준 - 연결 요소의 개수 : 11724번  (0) 2019.12.18
백준 - 윤년 : 2753번  (0) 2019.12.18
백준 - 고양이 : 10171번  (0) 2019.12.18
백준 - N과 M (2) : 15650번  (0) 2019.12.18
백준 - N과 M (1) : 15649번  (0) 2019.12.17

+ Recent posts