티스토리 뷰
solved.ac 티어 : 플5
https://www.acmicpc.net/problem/22348
이문제는 dp 문제있은데 dp인걸 알기 어렵다고 한다
이 문제는 빨강 페인트 a와 파랑 페인트 b 이렇게 두 개가 입력으로 들어오면 이 두 개의 양을 넘지 않는 선에서 만들 수 있는 모든 착륙장의 경우의 수를 출력하는 문제이다.
k개의 동심원인 착륙장을 만든다고 했을 때 k번째 동심원을 파랑 페인트를 칠한다고 하면 파랑 페인트는 b-k가 되고 남은 k-1개의 동심원은 a와 b-k만큼의 페인트로 칠해야 된다.
또는 k번째 동심원을 파랑 페인트로 칠하지 않는다고 했을때 파랑 페인트 양에는 변화가 없고 빨간색의 페인트는 a-k가 된고 k-1개의 동심원은 a-k, b만큼의 페인트로 칠해야 된다.
이 모든 걸 1,2,3,.... k번째 동심원까지 해줘야 된다.
이걸 2차원 배열로 나타 낼 수 있는데 dp [i][j]는 i번째 동심원일 때 파랑 페인트를 j만큼 썼을때의 경우의 수라고 정하자
그러면 dp[i][j]는 i번째 동심원일때 파랑 페인트를 쓰냐 안 쓰냐의 경우의 수를 더한 값이 된다.
즉 dp [i][j]=dp [i-1][j-i]+dp [i-1][j]가 된다.
이제 이렇게 dp 테이블을 만들어주고 문제의 첫 번째 예시 입력을 넣었을 때
i번째 동심원/파랑 페인트를 사용한 양 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
2 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
3 | 1 | 1 | 1 | 2 | 1 | 1 | 1 |
이런 테이블이 나온다.
열은 파랑 페인트의 사용량이기 때문에 b를 넘어간 위치는 버린다.
또 파랑 페인트를 j만큼 썼을 때 남은 부분은 빨강 페인트로 칠했다는 것인데 나머지 부분이 a보다 많으면 안 되니 많은 부분도 버린다. 즉 i*(i+1)/2-j <=a인 부분만 사용한다(i는 동심원의 수, j는 파랑 페인트의 사용량)
이제 위 두 조건을 만족하는 부분을 모두 더해주면 빨강 페인트 a와 파랑 페인트 b가 있을 때 만들 수 있는 착륙장의 모든 경우의 수를 구할 수 있다.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX=30;
ll MOD=1e9+7;
vector<ll>ch[502];
ll dp[502][50002];
vector<ll>st;
ll min(ll a,ll b){
if(a>b)return b;
else return a;
}
//최대 k 500
// 1부터 2,3,4,5... 순서대로 더했을때 50000을 넘지 않는 최대값은 49770이고 횟수는 315번
//dp[i][j]=i개의 동심원일때 파란색을 j만큼 썼을때의 가지수
int main(){
st.push_back(0);
ll cnt=0;
for(int i=0;i<500;i++)st.push_back(st[i]+i+1);
for(int i=1;i<501;i++){
ll Q=min(50000,st[i])+1;
ch[i].push_back(0);
for(int g=0;g<Q;g++){
if(i==1)dp[i][g]=1;
else{
dp[i][g]=dp[i-1][g];
if(g>=i)dp[i][g]+=dp[i-1][g-i];
}
ch[i].push_back(ch[i][g]+dp[i][g]);
dp[i][g]%=MOD;
}
}
ll a,b,c;
scanf("%lld",&a);
for(int W=0;W<a;W++){
scanf("%lld %lld",&b,&c);//빨,파
ll i=1,ans=0;
while(b+c>=st[i]){
ll z=min(st[i],c)+1;
if(z==st[i]-b)break;
ans+=ch[i][z];
if(st[i]>b){
if(ch[i][st[i]-b+1]==0)break;
ans-=ch[i][st[i]-b];
}
i++;
ans%=MOD;
}
printf("%lld\n",ans%MOD);
}
}
'ps' 카테고리의 다른 글
BOJ 6164(Hotel)풀이 (0) | 2021.08.07 |
---|---|
BOJ 1126(같은 탑)풀이 (0) | 2021.08.05 |
BOJ 1915(가장 큰 정사각형)풀이 (0) | 2021.07.15 |
BOJ 12784(인하니카 공화국)풀이 (0) | 2021.07.05 |
BOJ 8893(사냥꾼)풀이 (0) | 2021.07.02 |
- Total
- Today
- Yesterday
- 그래프 탐색
- 잡봇
- 정렬
- 그래프 이론
- 깊이 우선 탐색
- 세그먼트 트리
- 개발
- 이분 탐색
- 트리
- 누적 합
- C++
- 완전 탐색
- 이분매칭
- A Dance of Fire and Ice
- 수학
- 구현
- 그리디 알고리즘
- discord bot
- 트리에서의 다이나믹 프로그래밍
- 알고리즘
- 다이나믹 프로그래밍
- 자료구조
- 자료 구조
- 느리게 갱신되는 세그먼트 트리
- 선분 교차 판정
- Python
- BOJ
- codeforces
- KOI
- 최소 스패닝 트리
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |