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

 

19539번: 사과나무

첫 번째 줄에 모든 나무가 갊자가 바라는 높이가 되도록 물뿌리개를 통해 만들 수 있으면 “YES”를, 아니면 “NO”를 따옴표를 제외하고 출력한다.

www.acmicpc.net

 

 

[난이도] Gold5
[유형] 수학

[풀이]
1과 2가 무조건 동시에 사용되어야 하므로, 전체 수열의 합이 3의 배수여야 하고
(전체 수열의 합 / 3) = (물뿌리개를 사용해야 하는 횟수) = (2를 사용해야 하는 횟수) 이므로
1~N 사과나무들의 2로 나눈 몫의 합이 위의 (2를 사용해야 하는 횟수) 이상이어야 합니다.

이것을 만족하지 못하는 조건은 다음과 같이 표현이 가능합니다.
cnt : 2로 나눈 몫의 합
if(sum%3||cnt<sum/3) {
    puts("NO");
    return 0;
}

 

 

#include <cstdio>
int N,a[100000],sum,cnt;
int main(){
scanf("%d",&N);
for(int i=0;i<N;i++) {
scanf("%d",&a[i]);
sum+=a[i];
cnt+=a[i]/2;
}
if(sum%3||cnt<sum/3) {
puts("NO");
return 0;
}
puts("YES");
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold5/19539.cpp

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

 

18428번: 감시 피하기

NxN 크기의 복도가 있다. 복도는 1x1 크기의 칸으로 나누어지며, 특정한 위치에는 선생님, 학생, 혹은 장애물이 위치할 수 있다. 현재 몇 명의 학생들은 수업시간에 몰래 복도로 빠져나왔는데, 복

www.acmicpc.net

 

 

 

[난이도] Gold5
[유형] 브루트포스

[풀이]
N이 6이므로 최대 칸의 수는 36개입니다.
장애물을 놓을 수 있는 경우의 수는 X인 칸을 vector에 저장해놓고 3중 for문을 이용해
구할 수 있습니다.

세개의 위치의 X를 O로 바꾼 뒤 학생들이 검사를 피할 수 있는지 확인해보면 됩니다.

 

#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
int N,dy[4]={-1,1,0,0},dx[4]={0,0,1,-1};
char board[6][6];
vector<pair<int,int>> p,s;
bool check(){
for(auto [y,x] : s){
for(int i=0;i<4;i++){
int cy=y,cx=x;
while(cy>=0&&cx>=0&&cy<N&&cx<N&&board[cy][cx]!='O'){
if(board[cy][cx]=='T') return false;
cy+=dy[i],cx+=dx[i];
}
}
}
return true;
}
int main(){
scanf("%d",&N);
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
scanf(" %c",&board[i][j]);
if(board[i][j]=='X') p.push_back({i,j});
if(board[i][j]=='S') s.push_back({i,j});
}
}
int M = p.size();
for(int i=0;i<M-2;i++){
for(int j=i+1;j<M-1;j++){
for(int k=j+1;k<M;k++){
auto [y1,x1] = p[i];
auto [y2,x2] = p[j];
auto [y3,x3] = p[k];
board[y1][x1] = board[y2][x2] = board[y3][x3] = 'O';
if(check()) {
puts("YES");
return 0;
}
board[y1][x1] = board[y2][x2] = board[y3][x3] = 'X';
}
}
}
puts("NO");
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold5/18428.cpp

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

 

15661번: 링크와 스타트

첫째 줄에 N(4 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에 S가 주어진다. 각 줄은 N개의 수로 이루어져 있고, i번 줄의 j번째 수는 Sij 이다. Sii는 항상 0이고, 나머지 Sij는 1보다 크거나 같고, 100

www.acmicpc.net

 

 

[난이도] Gold5
[유형] 브루트포스

[풀이]
N 제한이 20밖에 되지 않기 때문에 모든 경우의 수를 해보는 브루트포스 알고리즘으로 해결이 가능합니다.
재귀와 비트마스크를 이용한 방법이 가능한데, 비트마스크를 이용하였습니다.

 

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int N,d[20][20],ans=9e8;
int main(){
scanf("%d",&N);
for(int i=0;i<N;i++)
for(int j=0;j<N;j++) scanf("%d",&d[i][j]);
for(int i=0;i<(1<<N);i++){
vector<int> a(N);
vector<int> p,q;
for(int j=0;j<N;j++){
if(i&(1<<j)) {
p.push_back(j);
a[j]=1;
}
else q.push_back(j);
}
if(p.empty() || q.empty()) continue;
int t1=0,t2=0;
for(int j=0;j<p.size();j++){
for(int k=0;k<p.size();k++){
t1+=d[p[j]][p[k]];
}
}
for(int j=0;j<q.size();j++){
for(int k=0;k<q.size();k++){
t2+=d[q[j]][q[k]];
}
}
ans=min(ans,abs(t1-t2));
}
printf("%d",ans);
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold5/15661.cpp

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

 

17218번: 비밀번호 만들기

첫째 줄과 둘째 줄에 수형이가 눈을 감고 만든 두 문자열이 주어진다. 문자열은 알파벳 대문자로만 이루어져 있으며, 길이는 최대 40자이다. 빈 문자열은 주어지지 않는다. 가장 긴 부분 문자열

www.acmicpc.net

 

 

[난이도] Gold5
[유형] DP

[풀이]
전형적인 LCS (DP) 문제입니다.

 

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
string A,B;
int dp[41][41];
pair<int,int> par[41][41];
int main(){
cin >> A >> B;
for(int i=0;i<A.size();i++){
for(int j=0;j<B.size();j++){
if(A[i]==B[j]) {
dp[i+1][j+1] = dp[i][j]+1;
par[i+1][j+1] = {i,j};
}else{
if(dp[i+1][j] > dp[i][j+1]){
dp[i+1][j+1] = dp[i+1][j];
par[i+1][j+1] = {i+1,j};
}else{
dp[i+1][j+1] = dp[i][j+1];
par[i+1][j+1] = {i,j+1};
}
}
}
}
string ans;
int i=A.size(),j=B.size();
while(i!=0&&j!=0){
if(A[i-1] == B[j-1]) ans+=A[i-1];
auto v = par[i][j];
i=v.first;
j=v.second;
}
reverse(ans.begin(),ans.end());
cout << ans;
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold5/17218.cpp

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

 

2253번: 점프

N(2 ≤ N ≤ 10,000)개의 돌들이 같은 간격으로 놓여 있다. 편의상 순서대로 1, 2, …, N번 돌이라고 부르자. 당신은 현재 1번 돌 위에 있는데, 이 돌들 사이에서 점프를 하면서 N번째 돌로 이동을 하려

www.acmicpc.net

 

 

[난이도] Gold4
[유형] DP

[풀이]
DP[n][k] : n = 현재 돌의 번호, k = 이전에 점프한 칸의 개수
k는 최악의 겨우에도
1+2+3+4+...k=10000
이므로 (k+1)k/2 = 10000 의 식을 이용하면 대략 500은 절대 넘지 않으므로
배열을 DP[10000][500] 으로 설정하여 메모리 초과를 피하였씁니다.

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int N,M,dp[10001][500],a[10000],inf=9e8;
int sol(int n,int k){
if(n==N) return 0;
if(n>N||a[n]) return -1;
int& ret = dp[n][k];
if(ret!=-1) return ret;
ret=inf;
for(int i=k-1;i<=k+1;i++){
if(i<1) continue;
int v = sol(n+i,i);
if(v==-1) continue;
ret=min(ret,v);
}
if(ret==inf) return ret=-1;
ret++;
return ret;
}
int main(){
scanf("%d%d",&N,&M);
while(M--){
int v;
scanf("%d",&v);
a[v]=1;
}
memset(dp,-1,sizeof(dp));
int ans = sol(2,1);
if(ans==-1) puts("-1");
else printf("%d",ans+1);
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold4/2253.cpp

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

 

16967번: 배열 복원하기

크기가 H × W인 배열 A와 두 정수 X와 Y가 있을 때, 크기가 (H + X) × (W + Y)인 배열 B는 배열 A와 배열 A를 아래로 X칸, 오른쪽으로 Y칸 이동시킨 배열을 겹쳐 만들 수 있다. 수가 겹쳐지면 수가 합쳐

www.acmicpc.net

 

 

[난이도] Silver3
[유형] 구현

[풀이]
두 배열의 겹치는 부분은 Bi,j = Ai,j + Ai-X,j-Y 와 같으므로
겹치는 부분의 A배열의 값은 A[i][j] = B[i][j] - A[i-X][j-Y] 의 식으로 구할 수 있습니다.
A[0][0] 부터 구하기 시작하면 A[i-X][j-Y]는 이미 구해져 있다는 것이 보장되기 때문에
위의 식에서 A[i-X][j-Y]이 없어서 못구하는 상황은 발생하지 않습니다.

 

#include <cstdio>
int H,W,X,Y,B[700][700],A[300][300];
int main(){
scanf("%d%d%d%d",&H,&W,&X,&Y);
for(int i=0;i<H+X;i++)
for(int j=0;j<W+Y;j++) scanf("%d",&B[i][j]);
for(int i=0;i<H;i++){
for(int j=0;j<W;j++){
if(i>=X && j>=Y) A[i][j] = B[i][j] - A[i-X][j-Y];
else A[i][j] = B[i][j];
printf("%d ",A[i][j]);
}
puts("");
}
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Silver3/16967.cpp

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

 

2210번: 숫자판 점프

111111, 111112, 111121, 111211, 111212, 112111, 112121, 121111, 121112, 121211, 121212, 211111, 211121, 212111, 212121 이 가능한 경우들이다.

www.acmicpc.net

 

 

[난이도] Silver2
[유형] 브루트포스

[풀이]
재귀함수를 이용해서 가능한 모든 경우를 구해주면 됩니다.

 

#include <cstdio>
#include <set>
#include <string>
#include <cstring>
using namespace std;
int dy[4]={-1,1,0,0},dx[4]={0,0,1,-1},board[5][5],ans;
set<string> st;
void sol(int y,int x,string s){
if(s.size()==6){
st.insert(s);
return;
}
for(int i=0;i<4;i++){
int ny=y+dy[i],nx=x+dx[i];
if(ny<0||nx<0||ny>=5||nx>=5) continue;
char c = board[ny][nx]+'0';
string t;
t=s+c;
sol(ny,nx,t);
}
}
int main(){
for(int i=0;i<5;i++)
for(int j=0;j<5;j++) scanf("%d",&board[i][j]);
for(int i=0;i<5;i++){
for(int j=0;j<5;j++){
string t;
t+=(board[i][j]+'0');
sol(i,j,t);
}
}
printf("%d",st.size());
}

 


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Silver2/2210.cpp

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

 

15664번: N과 M (10)

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

www.acmicpc.net

 

 

[난이도] Silver2
[유형] 백트래킹

[풀이]
오름차순으로 출력해야 하기 때문에 정렬 후에 백트래킹을 해주면 됩니다.
중복 제거를 위해 set을 이용하였습니다.

 

#include <cstdio>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
int N,M,a[8];
set<vector<int>> st;
vector<int> ans;
void sol(int n){
if(n==N){
if(ans.size()==M) {
if(st.find(ans) == st.end()){
st.insert(ans);
for(auto k : ans) printf("%d ",k);
puts("");
}
}
return;
}
ans.push_back(a[n]);
sol(n+1);
ans.pop_back();
sol(n+1);
}
int main(){
scanf("%d%d",&N,&M);
for(int i=0;i<N;i++) scanf("%d",&a[i]);
sort(a,a+N);
sol(0);
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Silver2/15664.cpp

+ Recent posts