1번
계단오르기,숏다리 계단, 찬스 등 숙지하자. 원리는 같다. 필요한 상태가 있으면 함수에
추가해서 해결하면 된다.
f(n, k) = n칸을 정확히 k번 이동해서 올라가는 방법의 수
#include <stdio.h>
int f(int n, int k) {
if (k == 0) return n == 0 ? 1 : 0; // 이동을 다 썼으면 딱 도착했을 때만 1
if (n <= 0) return 0; // 이동이 남았는데 더 갈 칸이 없음
return f(n - 1, k - 1) + f(n - 2, k - 1) + f(n - 3, k - 1);
}
int main() {
int n, k;
scanf("%d %d", &n, &k);
printf("%d\n", f(n, k));
}
2번
광석수집 문제에서 방향하나 추가하면 된다.
#include <stdio.h>
#define EMPTY -1000000000 // 아직 안 구했다는 표시 (실제 합으로는 절대 나올 수 없는 값)
int n, m;
int A[1001][1001];
int memo[1001][1001]; // (r, c)에서 도착 칸까지의 최대 합
int max(int a, int b) { return a > b ? a : b; }
int f(int r, int c) {
if (r > n || c > m) return EMPTY; // 격자 밖: 절대 고르지 않게 아주 작은 값
if (r == n && c == m) return A[r][c]; // 도착 칸
if (memo[r][c] != EMPTY) return memo[r][c]; // 이미 구한 값
int best = max(f(r, c + 1), max(f(r + 1, c), f(r + 1, c + 1)));
memo[r][c] = A[r][c] + best;
return memo[r][c];
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
scanf("%d", &A[i][j]);
memo[i][j] = EMPTY; // 처음엔 전부 안 구했다고 표시
}
printf("%d\n", f(1, 1));
return 0;
}
3번
다이아몬드출력, 모래시계출력같은거는 관계기반으로 출제하기가 어려우니까
출제가 되더라도 그냥 단순 재귀함수 여러개로 풀게할 가능성이 높다.
if(k==0) return;
f(k-1);
s[k]='*';
s[k-1]=' ';
puts(s+1);
4번
#include <stdio.h>
int n;
int A[128][128];
int mx[129]; // mx[size]: 한 변이 size인 영역들의 가치 중 최댓값 (size = 1, 2, 4, ..., n만 사용)
int f(int r, int c, int size) {
int sum=0;
if (size == 1) {
sum = A[r][c]; // 한 칸짜리
} else {
int h = size / 2;
sum = f(r, c, h)
+ f(r, c + h, h)
+ f(r + h, c, h)
+ f(r + h, c + h, h);
}
if (sum > mx[size]) mx[size] = sum; // 이 크기의 최댓값 갱신
return sum;
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &A[i][j]);
for (int s = 1; s <= n; s *= 2) mx[s] = -2000000000; // 음수도 나오니까 아주 작은 값으로 시작
f(0, 0, n);
for (int s = 1; s <= n; s *= 2) printf("%d\n", mx[s]);
}
5번
은근 어렵다
#include <stdio.h>
int K;
int cnt, ans[31];
int min(int a, int b) { return a > b ? b : a; }
void f(int n, int lo) {
if (n == 0) {
printf("%d", ans[0]);
for (int i = 1; i < cnt; i++) printf(" %d", ans[i]);
printf("\n");
return;
}
for (int i = lo; i <= min(n, K); i++) { // 직전 수 이상만 골라서 오름차순 유지
ans[cnt++] = i;
f(n - i, i);
cnt--;
}
}
int main() {
int n;
scanf("%d %d", &n, &K);
f(n, 1);
return 0;
}
6번
#include<stdio.h>
void f(int n,int k){
if(n==0) return;
f(n/k,k);
if(n%k<10) printf("%d",n%k);
else printf("%c",n%k+'A'-10);
}
int main(){
int n,k;
scanf("%d%d",&n,&k);
if(n==0) printf("0");
else f(n,k);
}