수 묶기
https://www.acmicpc.net/problem/1744
길이가 N인 수열이 주어졌을 때, 그 수열의 합을 구하려고 한다. 하지만, 그냥 그 수열의 합을 모두 더해서 구하는 것이 아니라, 수열의 두 수를 묶으려고 한다. 어떤 수를 묶으려고 할 때, 위치에 상관없이 묶을 수 있다. 하지만, 같은 위치에 있는 수(자기 자신)를 묶는 것은 불가능하다. 그리고 어떤 수를 묶게 되면, 수열의 합을 구할 때 묶은 수는 서로 곱한 후에 더한다.
예를 들면, 어떤 수열이 {0, 1, 2, 4, 3, 5}일 때, 그냥 이 수열의 합을 구하면 0+1+2+4+3+5 = 15이다. 하지만, 2와 3을 묶고, 4와 5를 묶게 되면, 0+1+(2*3)+(4*5) = 27이 되어 최대가 된다.
수열의 모든 수는 단 한번만 묶거나, 아니면 묶지 않아야한다.
수열이 주어졌을 때, 수열의 각 수를 적절히 묶었을 때, 그 합이 최대가 되게 하는 프로그램을 작성하시오.
도대체 수를 왜 묶냐
음수일 때 고려 안 해서 한 번 틀리고
홀수, 짝수 조건 거꾸로 해서 한 번 더 틀리고
인덱스 잘못 접근해서 한 번 더 틀리고 드디어 맞았다.
그렇다 이 문제는 정렬한 상태에서
1. 원소가 음수이고 해당 인덱스가 짝수일 때
-> 그 원소를 제외한 음수가 짝수개이므로 곱하지 않고 넘어간다(인덱스가 작아질수록 절댓값이 커지므로)
2. 원소와 그 다음 원소를 곱했을 때의 값이 0 이하일 때
-> 경계를 잘 고려해주어야 한다. 이때 해당 인덱스가 홀수고 곱해서 0이 된다면 곱하는 것이 이득
3. 원소와 그 다음 원소를 곱했을 때의 값이 양수일 때(양수*양수, 음수*음수)
-> 무조건 곱하는 게 이득이다.
그리고 1일때는 인덱스 -1, 2와 3일 때는 인덱스 -2 해줘야 한다.
더 효율적인 게 있을지 모르지만 나는 이렇게 풀었다.
역시 돌려봐야 맞을지 틀릴지도 아는데 틀리면서 돌리는 습관은 좀 고쳐야할 듯
코드
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 | #include <iostream> #include <algorithm> using namespace std; int main(){ cin.tie(); int N; cin>>N; int series[N], i; for(i=0; i<N; i++) cin>>series[i]; if(N==1){ cout<<series[0]; return 0; } //위치에 상관없이 묶을 수 있으므로 정렬 sort(series, series+N); long long sum=0; i=N-1; while(i>0){ if(series[i]<0&&i%2==0){ i--; continue; } if(series[i]*series[i-1]<=0&&i%2==1){ if(series[i]==0){ series[i]*=series[i-1]; series[i-1]=0; } i=i-2; continue; } //양수*양수, 음수*음수의 경우 if(series[i]*series[i-1]>0){ series[i]=max(series[i]+series[i-1], series[i]*series[i-1]); series[i-1]=0; //i-1번째 원소는 건너뛰어도 됨 i=i-2; continue; } i--; } for(i=0; i<N; i++){ sum+=series[i]; } cout<<sum<<endl; return 0; } | cs |
'PS' 카테고리의 다른 글
백준 10819번 C++ 순열 활용 문제 (0) | 2019.09.18 |
---|---|
백준 11723번 C++ 집합 정답률이 낮은 이유 (0) | 2019.09.17 |
백준 1654번 C++ 랜선 자르기 (0) | 2019.06.28 |
백준 2178번 C++ 미로 탐색 (0) | 2019.06.26 |
백준 9466번 C++ 텀 프로젝트 (0) | 2019.06.15 |
댓글