본문 바로가기
카테고리 없음

Codeforce)Edu33_D_Creditcard

by 박정률 2017. 11. 26.

The problem in short : 

* 저녁에는 돈을 입금하거나 ( ai < 0 ), 돈을 출금하거나 ( ai > 0) , 돈이 얼마있는지 확인( ai == 0) 을 한다.

* 단  통장에는 항상  d 보다 작거나 같은 돈이 들어있어야 하고,

*  돈을 확인할때 0이상의 돈이 존재해야 한다.

따라서 아침에 은행을 방문하는 횟수를 최소로할 때 방문횟수를 출력하자, ( 불가능하면  -1) 


The solution : 

* 은행 방문 횟수를 최소로 하기 위해서는 돈을 넣을 수 있는 한 많이 넣어야한다.

* 하지만 넣을 수 있는 한도는 뒤에 있는 입금을 고려할 떄 d를 초과하지 않아야 한다.

* 이렇게 넣는게 optimal 한가?

* 귀류법 ) 돈을 이거보다 적게 넣는다고 가정했을 때 -> 전혀 이득 볼 게 없다. 어차피 넘칠 일 은 없고, 나중에 은행 갈 횟수를 늘리게 될뿐

* 돈을 확인하는 날의 아침에 0이상이라면 은행을 가지않고, 0보다 작다면 최대한 넣을 수 있는만큼 많이 넣는다.

* 불가능 한날은? 현재 내 잔고가 음수라서 돈을 넣어야 하는데 뒤에서 넘칠 까봐 돈을 넣을 수 없는 상황이라면.

1) 넣을 수 있는 최댓값을 계산한다.

2) 이 최댓값이 음수라면 돈을 넣을 수 없는 상황이므로 불가능

3) 돈을 넣었는데에도 음수라면 불가능

* 아예 0 이 등장하지 않을 수 도 있으므로 잘 처리해줄 것


The code : 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <cstdio>
#include <algorithm>
 
using namespace std;
typedef long long ll;
ll n,d;
ll a[101000];
ll sum[101000];
ll maxifromend[101000];
int main(){
freopen("input.txt","r",stdin);
scanf("%lld %lld",&n,&d);
for(int i = 1 ; i <= n ; i++){
    scanf("%lld",&a[i]);
}
 
for(int i = 1; i <= n ; i++){
    sum[i] = sum[i-1+ a[i];
}
ll maxi = -10000000000;
for(int i = n ; i >=1; i--){
    maxi = max(maxi,sum[i]);
    maxifromend[i] = maxi - sum[i-1];
}
 
if(maxi > d){
    printf("-1");
    return 0;
}
ll curr = 0;
int cnt = 0;
bool flag = 1;
for(int i = 1; i <= n ; i++){
    if(a[i] == 0){
        if(curr >= 0){
            continue;
        }
        else{
 
            int deposit = d - maxifromend[i] - curr;
            if(deposit < 0){
                flag = 0;
                break;
            }
            if(deposit + curr < 0 )
            {
                flag = 0;
                break;
            }
            else{
                curr += deposit;
                cnt++;
            }
        }
    }
    else{
        curr += a[i];    
        if(curr > d){
            flag = 0;
            break;
        }
    }
}
 
if(flag)
printf("%d",cnt);
else
puts("-1");
 
 
 
}
cs



The feedback : 

1.  조건을 하나하나 잘 따지기

2. 나올 수 있는 범위 미리 잘 파악하기. ( maxi 값을 0부터 잡아버리는 실수 때문에 시간잡아먹음)