codeforce 1400
COFO::1415C Bouncing Ball
cofo problem
COFO::1415C Bouncing Ball
Problem
- level : 1400
- tag : brute force, dp, implementation
- 아이디어가 어렴풋이 떠올랐을때 이걸 어떻게 코드로 표현할지, 복잡도가 정확히 in time 가능한지에 대해 생각해보았고,
- 이게 이렇게 하면 시간내에 충분히 돌겠다 라는 확신을 가지는 순간 PS가 주는 쾌감이 있는 것 같은 문제였습니다.
Point
- n 개의 박스로 이루어진 string s 가 주어집니다.
- 박스가 비어있는 곳은 0, 존재하는 곳은 1로 표시합니다.
- 공을 떨어뜨리는 첫번째 위치는 앞에서부터 p번째 박스이며, 공은 k칸만큼 바운스됩니다.
- 이때 사용할 수 있는 2가지 작업이 있습니다.
- x초가 소모되는 작업은, 비어있는 i번째 박스를 채우는 것입니다.
- y초가 소모되는 작업은, 맨 앞 인덱스에있는 박스를 통째로 제거해서 인덱스를 모두 하나씩 늘리는 방법입니다.
- 위의 작업을 사용해서, 최소의 초가 소모되도록 공을 바운스 시킵니다.
- 단, 공이 바운스되는 박스는 항상 채워져있어야 하며, 박스는 최소 p개 존재해야합니다.
Design
- 매우 복잡해보이지만, x, y 작업 몇개를 해보면 규칙을 찾을 수 있습니다.
- 그 규칙은 다음과 같습니다.
- 공이 k칸씩 바운스됩니다.
- 즉, 앞에 박스가 몇개가 없어졌건 k칸씩 바운스 된다는 의미입니다.
- 위의 정보를 이용해서 다음과 같은 방법으로 문제를 해결할 수 있습니다.
- p번째에 공이 첫번째로 튀기는 집합
- p+1번째에 공이 첫번째로 튀기는 집합(이때는 맨 앞 하나를 제거한다는 의미)
- p+2번째에 공이 첫번째로 튀기는 집합(이때는 맨 앞 두개를 제거한다는 의미)
- …
- p+k번째에 공이 첫번째로 튀기는 집합(이때는 맨 앞 k개를 제거한다는 의미)
- 다행히도 p+k까지만 생각하면 됩니다.
- p+k+1번째의 경우, p번째에 공이 첫번째로 튀기는 것에 포함된 집합이기때문입니다.
- 이때, 앞의 k개만 제거해주면 같은 집합이 되겠지요
- 결국, 총 k개의 집합이 존재합니다.
- 각 집합에서 공이 바운스되는 위치는 정해져있습니다.
- 즉, 01110 처럼 해당 집합의 원소들을 나열할 수 있습니다.
- 해당 집합에 포함된 0과 1의 갯수를 모두 세어주는 작업을 먼저 진행합니다.
- 이후, 앞에서부터 하나씩 제거하며 x와 y초를 계산해주면 됩니다.
- ex) 0110 -> 110 -> 10 -> 0
Big O(time)
- O(N)
Code
#define rep(i, a, b) for(int i = (a); i<(b); i++)
#define r_rep(i, a, b) for(int i=(a); i>(b); i--)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
string s;
int x, y;
int n, p, k;
int mn;
void input(){
mn = 1000000001; // p = 100000이고 y 가 10000 인경우 max
cin >> n >> p >> k >> s >> x >> y;
}
void solve(){
input();
p -= 1;
rep(i, 0, k+1){
int st = p + i;
string tmp = "";
int cur = st;
int cnt0 = 0, cnt1 = 0;
while(cur < n){
if(s[cur] == '1') cnt1++;
else cnt0++;
tmp += s[cur];
cur += k;
}
cur = 0;
int cntDel = i;
while(cur < (int)tmp.size()){
int sum = cnt0 * x + y * cntDel;
mn = min(mn, sum);
cntDel += k;
if(tmp[cur] == '0') cnt0--;
cur += 1;
}
}
cout << mn << '\n';
}
int main(){;
//freopen("input.txt", "r", stdin);
int tc; cin >> tc;
while(tc--)
solve();
return 0;
}